11
$\begingroup$

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}}
$\endgroup$
0

3 Answers 3

25
$\begingroup$

You could use Apply at the first level:

Times @@@ listA
$\endgroup$
22
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ Thank You very much for the Detailed explanation $\endgroup$
    – 500
    Feb 18, 2012 at 21:49
7
$\begingroup$

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
$\endgroup$
5
  • 1
    $\begingroup$ 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. $\endgroup$
    – rcollyer
    Feb 19, 2012 at 2:09
  • $\begingroup$ @rcollyer thank you :-) $\endgroup$
    – Mr.Wizard
    Feb 19, 2012 at 2:20
  • $\begingroup$ 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. $\endgroup$
    – JimiLoe
    May 24, 2016 at 17:15
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    May 25, 2016 at 1:58
  • $\begingroup$ @Mr.Wizard You are right. I tested it with a flat list and not a nested one. Thank you for your quick response! $\endgroup$
    – JimiLoe
    May 25, 2016 at 7:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.