10
$\begingroup$

I have a function that grabs the second part of the list and change it to times,

mylist = {{{y1, y2, y3}, {y3, y4, y5}}, {{w1, w2, w3}, {w4, w5, w6}}};
g[x_] := x /. List -> Times
Map[g, mylist, {2}]

I wrote it above, but I think I should be able to make it much simpler code using @ # and &. Any suggestion?

$\endgroup$
2
  • 1
    $\begingroup$ FWIW: you don't need to define g: you can use /. as an operator directly: Map[ReplaceAll[List -> Times], mylist, {2}], or even Map[# /. List -> Times &, mylist, {2}]. $\endgroup$ Commented Jun 30, 2019 at 1:42
  • 1
    $\begingroup$ Idiomatic way is to use: Apply[Times, mylist, {2}]. It is short and easy to understand. $\endgroup$
    – Ray Shadow
    Commented Jul 1, 2019 at 22:17

12 Answers 12

12
$\begingroup$

Since you appear to want to multiply the list only when all of its elements are atomic, how about just

mylist /. {s__?AtomQ} :> Times[s]

It appears to be the most direct translation of your thought.

$\endgroup$
16
$\begingroup$
☺lookMaNoLetters☺ = 1 ## & @@@ # & /@ # &;

☺lookMaNoLetters☺ @ mylist

{{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}

Further variations:

☺lookKidNoLettersOrNumbers☺ = # ##2 & @@@ # & /@ # &;

☺ApplyTimesAtLevel2☺ = # ##2 & @@ ## &[#, {2}] &;

☺InCaseYouLikeInfix☺ = # ~ (# ##2 & @@ ## &) ~ {2} &;

☺IfYouLikeVerbose☺ = Map @* MapApply @ Times

You can use as many @s as you like:

☺♬♪♫♪☺ = ## & @@@ (## & @@@ ## & @@@ 1 ## & @@@ {##} & @@@ {##} & /@ #) &;

☺♬♪♫♪☺ @ mylist

{{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}

$\endgroup$
2
  • 5
    $\begingroup$ I'd add a disclaimer suggesting OP should not actually code this way... $\endgroup$
    – lirtosiast
    Commented Jul 1, 2019 at 3:39
  • 1
    $\begingroup$ What a fun answer! I already accept the answer, but it is amazing, and very helpful for me to understand the language. Thanks $\endgroup$
    – Saesun Kim
    Commented Jul 1, 2019 at 7:23
7
$\begingroup$
Times @@@ # & /@ mylist
(*    {{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}    *)
$\endgroup$
3
  • 6
    $\begingroup$ This seems less clear and less general than Apply[Times, mylist, {2}] or ...{-2}. $\endgroup$
    – lirtosiast
    Commented Jun 29, 2019 at 16:39
  • 5
    $\begingroup$ @lirtosiast oh yes for sure, but the OP was specifically asking for @ # & gobbledygook :-) Ideally there would be a @@@@ operator for this purpose. $\endgroup$
    – Roman
    Commented Jun 29, 2019 at 16:48
  • $\begingroup$ Thank you so much for the clear and nice answer! $\endgroup$
    – Saesun Kim
    Commented Jun 29, 2019 at 16:59
5
$\begingroup$

Another way to view your function is as a generalized inner product:

Inner[Times, mylist, {1, 1, 1}, Times]
{{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}
$\endgroup$
5
$\begingroup$
Map[Times[Sequence @@ #] &] /@ mylist
(* {{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}} *)
$\endgroup$
3
$\begingroup$

Apply can be used with level specificator in the same way as Map:

Apply[Times, mylist, {2}]

{{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}

$\endgroup$
3
$\begingroup$

If mylist is a depth-three rectangular array, the following will work; if it is also packed, this will minimally unpack and produce a packed array:

Times @@ Transpose[mylist, {2, 3, 1}]
(*  {{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}  *)

More obfuscatory fun:

Block[{★},
 ★ /: {x__★} := Block[{★ = # &}, 1 x];
 Function[s, ★@s, Listable]@mylist
 ]
(*  {{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}  *)
$\endgroup$
1
  • $\begingroup$ You could also compile for no unpacking (_Real or _Integer, but in separate functions): cf = Compile[{{a, _Real, 3}}, Times @@ Transpose[a, {2, 3, 1}]]; cf@myarray. Or force Apply to compile with SetSystemOptions["CompileOptions" -> "ApplyCompileLength" -> 0];. $\endgroup$
    – Michael E2
    Commented Jul 1, 2019 at 4:28
3
$\begingroup$
list = {{{y1, y2, y3}, {y3, y4, y5}}, {{w1, w2, w3}, {w4, w5, w6}}};

Using MapApply (new in 13.1)

MapApply[Times] /@ list

{{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}

$\endgroup$
2
$\begingroup$
list = {{{y1, y2, y3}, {y3, y4, y5}}, {{w1, w2, w3}, {w4, w5, w6}}};

Using MapApply and Transpose as follows:

Times @@ Transpose@{##} & @@@ list

(*{{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}*)

Or using Replace at level 2:

Replace[list, v_ :> Times @@ v, {2}]

(*{{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}*)
$\endgroup$
2
$\begingroup$
mylist = {{{y1, y2, y3}, {y3, y4, y5}}, {{w1, w2, w3}, {w4, w5, w6}}};

rule = x_?VectorQ :> Times @@ x;
mylist /. rule

{{y1 y2 y3, y3 y4 y5}, {w1 w2 w3, w4 w5 w6}}

$\endgroup$
1
$\begingroup$

Using Map:

Map[Times[Delete[#,0]]&, mylist, {2}]

(* {{y1 y2 y3,y3 y4 y5},{w1 w2 w3,w4 w5 w6}} *)

$\endgroup$
1
  • 1
    $\begingroup$ +1, Very nice and flexible (replace 0 with 1 etc.) $\endgroup$
    – eldo
    Commented Feb 5 at 16:45
-1
$\begingroup$

Been a while since I coded in Wolfram...

Times @@ mylist[[2]]

So long that I had to look up indexing.

$\endgroup$
2
  • $\begingroup$ Almost forgot that Mathematica had a nifty set of ways to specify indexing. Ones that I tried to copy. $\endgroup$
    – kozner
    Commented Jun 30, 2019 at 9:04
  • 1
    $\begingroup$ This produces {w1 w4, w2 w5, w3 w6}, which is not close to what is sought. (It's good site practice to include the output of your code, when it's not too long.) Makes you wonder about the upvote, though, doesn't it. $\endgroup$
    – Michael E2
    Commented Jul 1, 2019 at 3:58

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.