11

Please Consider :

list={{5,2,6},{2,8,3}}

I need to get the product of all the element within list :

As of now I do this :

(#[[1]]*#[[2]]*#[[3]]) & /@ list

Which means I have to manually specify the number of elements within each least and the sublists length has to b equal.

How could do this automatically to automatically deal with the following case ?

listA={{5,2,6,3},{2,8,3,4}}
listB={{5,2,6},{2,4}}
Kuba
  • 136,707
  • 13
  • 279
  • 740
500
  • 5,569
  • 6
  • 27
  • 49

3 Answers3

25

You could use Apply at the first level:

Times @@@ listA
Heike
  • 35,858
  • 3
  • 108
  • 157
22

Short answer: See Heike's post.

Longer version:

There are a couple of functions in the functional programming toolbox that are so common that they've gotten their own symbols. One of them is Apply, which takes a list and uses its elements as function arguments:

Apply[f, {a, b, c}]
f[a, b, c]

The shorthand notation for this would be f @@ {a, b, c}.

Additionally, Apply has an optinal third argument, specifying the depth at which the function should be applied:

(* Apply on 0-th level *)
Apply[f, {{a,b}, {c,d}}]
f[{a,b}, {c,d}]
(* Apply on the first level *)
Apply[f, {{a,b}, {c,d}}, {1}]
{f[a,b], f[c,d]}

The latter is also a very common expression, it has the shorthand notation f @@@ {{a,b}, {c,d}}. The notation ends here, i.e. there's no @@@@; if you need that, you'll have to use Apply explicitly. The documentation features plenty of examples if you need further help.

That said, what you want is converting a list of lists of numbers to a list of the product of the numbers. This is equivalent to applying the product function on the first level of the original list; that function is called Times in Mathematica (Product stands for the mathematical expression $\prod_a^bx$). Times is the internal function that is called when you enter something like a*b*c: it becomes Times[a,b,c] internally. Therefore, using the Apply function from above,

Apply[Times, {{a,b}, {c,d}}, {1}]

(* Evaluates to ... *)
{Times[a,b], Times[c,d]}

(* ... and is equivalent to ... *)
{a b, c d}

That's precisely what you want. Adding the syntactic sugar from above, @@@, this leaves you with the final short notation

Times @@@ list

to solve the problem.

David
  • 14,911
  • 6
  • 51
  • 81
7

Just for fun:

Replace[list, {x__} :> 1 x, 1]

Since this answer has garnered some votes here is a more direct form of the implicit Times:

1##& @@@ list
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • 1
    Nice. Implicitly passing x to Times by prefixing it with a 1, and because it is a Sequence it becomes Times[1, x]. Very clever. – rcollyer Feb 19 '12 at 02:09
  • @rcollyer thank you :-) – Mr.Wizard Feb 19 '12 at 02:20
  • I think, the implicit version should be 1##& @@ list - with @@ instead of @@@. 1##& @@@ list will apply Times on nesting level 1 instead of 0, and will therefore simply return the unchanged list. – JimiLoe May 24 '16 at 17:15
  • @JimiLoe I wish to always be open to correction, but in this case I do not believe I made a mistake. 1 ## & @@@ {{5, 2, 6}, {2, 8, 3}} evaluates to {60, 48} which is the same as the original code (#[[1]]*#[[2]]*#[[3]]) & /@ {{5, 2, 6}, {2, 8, 3}}. 1 ## & @@ {{5, 2, 6}, {2, 8, 3}} evaluates to {10, 16, 18} which is a different result. – Mr.Wizard May 25 '16 at 01:58
  • @Mr.Wizard You are right. I tested it with a flat list and not a nested one. Thank you for your quick response! – JimiLoe May 25 '16 at 07:04