7
$\begingroup$

For example, consider the list defined below.

samplelist = {{{1,2,3,4}}, {{5,6,7,8}}};

How would I apply the Times operator to the subsets {1,2,3,4} and {5,6,7,8}?

Neither Map nor Apply work (or at least not in the ways I've tried).

If somebody could please help me out, I'd greatly appreciate it. I seem to run into this problem of trying to circumvent extra curly brackets quite often.

Edit: Sorry for not clarifying. The desired output is {24,1680}. Extra brackets are fine for something like {{24},{1680}} since at this point, Flatten can be used.

$\endgroup$
7
  • 1
    $\begingroup$ You can remove the extra brackets: Apply[Times, Flatten[samplelist, 1]] $\endgroup$
    – bill s
    Commented Jun 28, 2015 at 6:36
  • $\begingroup$ When I try that, how come the output is {5,12,21,32}? I experienced something similar when I tried using Table. $\endgroup$
    – user155812
    Commented Jun 28, 2015 at 6:39
  • 3
    $\begingroup$ E.g., Apply[Times, samplelist, {2}]... and Apply[Times, samplelist, -2] will do it for a list of lists with differing depths... $\endgroup$
    – ciao
    Commented Jun 28, 2015 at 6:40
  • $\begingroup$ Ah, it's because Flatten turns samplelist into all into one list, which isn't what I want. I want to apply Times to each element separately. Sorry for not clarifying. $\endgroup$
    – user155812
    Commented Jun 28, 2015 at 6:40
  • $\begingroup$ Please state for your example what you want the output to be. $\endgroup$
    – bill s
    Commented Jun 28, 2015 at 6:40

5 Answers 5

11
$\begingroup$

I suspect you'd be fine with

samplelist /. {x__Integer} :> Times@x // Flatten

If you always store numbers you want to multiply in lists, and you know them to be integers, this will “apply” Times to all such lists in your data.

For more general numbers try something like

samplelist /. {x__?NumberQ} :> Times@x // Flatten

Note: this way you don't have to adjust Apply's (positive) levelspec to every single data sample you're dealing with, which is handy if you don't know in advance what depth exactly your lists will have, and if you also have lists of atoms you don't want to multiply. In absence of the latter condition, Mr Wizard's answer is probably better.

$\endgroup$
8
$\begingroup$

If elements are atomic you can use levelspec {-2}:

Apply[Times, samplelist, {-2}]
{{24}, {1680}}

Since Plus[x] and Times[x] each reduce to x you can also use -2 if you not want the extra brackets, as shown by ciao (rasher):

Apply[Times, samplelist, -2]
{24, 1680}

With a dummy head foo to see how this works:

Apply[foo, samplelist, -2]
{foo[foo[1, 2, 3, 4]], foo[foo[5, 6, 7, 8]]}

Some reading for you:

$\endgroup$
2
  • $\begingroup$ I'm not really sure why this question isn't closed. p.s. # /. List -> Times & /@ samplelist $\endgroup$
    – Kuba
    Commented Jun 28, 2015 at 11:05
  • 1
    $\begingroup$ @Kuba Do not let my answer dissuade you from voting to close! $\endgroup$
    – Mr.Wizard
    Commented Jun 28, 2015 at 11:05
3
$\begingroup$

Another approach, perhaps only slightly different than @Akater's:

samplelist /. v_?VectorQ :> Times @@ v
(*  {{24}, {1680}}  *)

One can give VectorQ other arguments that restrict what type of elements the vector v might contain. By default, an element can be anything except a list.

For example:

{{{x, Exp[x], 3, 4, x Exp[x]}},
 {{{5, Plot[Sin[x], {x, 0, 2 Pi}], Plot[Sin[x], {x, 0, 2 Pi}]}}}} /.
  v_?VectorQ :> Times @@ v

Mathematica graphics

$\endgroup$
1
$\begingroup$
Times @@@ samplelist ~Flatten~ 1

{24, 1680}

One could also directly Replace the innermost List with Times

Replace[samplelist, List -> Times, {3}, Heads -> True] // Flatten

{24, 1680}

$\endgroup$
6
  • $\begingroup$ Isn't that bill's answer ? $\endgroup$
    – Sektor
    Commented Jun 29, 2015 at 9:08
  • $\begingroup$ @Sektor bills comment is Apply[Times, Flatten[samplelist, 1]], which doesn't give the correct output. This is Apply[Times, Flatten[samplelist, 1], {1}] and does give the correct output. $\endgroup$
    – Karsten7
    Commented Jun 29, 2015 at 9:16
  • $\begingroup$ I was talking about being the same answer as an idea. Clearly, there's a difference between the two, but you are assuming the OP is not going to experiment any further with the answers/suggestions he receives. $\endgroup$
    – Sektor
    Commented Jun 29, 2015 at 9:28
  • $\begingroup$ I completely disagree with the assumptions about the OP and about the actions by the OP, that the comment by @Sektor assumes about me. $\endgroup$
    – Karsten7
    Commented Jun 29, 2015 at 19:25
  • $\begingroup$ Then the difference between your answer and bill's is just philosophical $\endgroup$
    – Sektor
    Commented Jun 29, 2015 at 19:30
1
$\begingroup$

Some more options:

New in 12.2

ArrayReduce[Apply @ Times, list, 3]

{{24}, {1680}}

New in 13.1

ReplaceAt[list, x_ :> Times @@ x, {;; , ;;}]

{{24}, {1680}}

Query[;; , ;; , Apply @ Times] @ list

{{24}, {1680}}

$\endgroup$

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