For some function f, consider the following expression:

 f[2] f[5] - f[1] f[2] f[5] - f[2] f[3] f[5] + f[1] f[2] f[3] f[5] - f[2] f[4] f[5] + f[1] f[2] f[4] f[5] + f[2] f[3] f[4] f[5] - f[1] f[2] f[3] f[4] f[5]

How can I manipulate this expression so that it instead reads:

f[2,5] - f[1,2,5] - f[2,3,5] + f[1,2,3,5] - f[2,4,5] + f[1,2,4,5] + f[2,3,4,5] - f[1,2,3,4,5]

I.e. the function is now implemented on a list of the individual arguments. I've had a go at trying Map to achieve this but with no luck.


To make this more meaningful for functions, how can the above string be passed as a single vector. Specifically, how can we obtain the output

f[{2,5}] - f[{1,2,5}] - f[{2,3,5}] + f[{1,2,3,5}] - f[{2,4,5}] + f[{1,2,4,5}] + f[{2,3,4,5}] - f[{1,2,3,4,5}],

this form can then be applied to a predefined function f[u] that operates on the list u. The function should also be able to take additional arguments.


Try using upvalues:

Times[f[x__], f[y__]] ^:= f[x, y]

and then evaluating the expression f[2] f[5] - f[1] f[2] f[5] - ... again.

You could also do it without modifying f and using ReplaceRepeated (//.):

expr //. Times[f[x__], f[y__]] :> f[x, y]
  • $\begingroup$ This works great. Sometimes, it doesn't apply the same ordering. I.e. f[2] f[3] f[5] //. Times[f[x__], f[y__]] :> f[x, y] gives f[5, 2, 3] not f[2, 3,5]. Is there a simple fix for this? $\endgroup$ – Sid Mar 19 at 0:12
  • 2
    $\begingroup$ @Sid - Once you have defined UpValues for f you do not need to use /. or //. If you want the arguments ordered use ClearAll[f]; Times[f[x__], f[y__]] ^:= f @@ Sort[{x, y}] Then just evaluate f[2] f[3] f[5] and the result will be f[2, 3, 5] $\endgroup$ – Bob Hanlon Mar 19 at 0:56
  • $\begingroup$ @Sid Another way: you can evaluate SetAttributes[f, Orderless], and f will thereafter always automatically put its arguments in canonical order (the same ordering Times uses). $\endgroup$ – thorimur Mar 19 at 4:03
  • 1
    $\begingroup$ @Sid expr //. Times[f[x__], f[y__]] :> f[x, y] /. f[x__] :> f[{x}] $\endgroup$ – wuyudi Mar 19 at 15:26
  • 1
    $\begingroup$ @Sid Or expr //. Times[f[x__], f[y__]] :> f[x, y] /. f :> (f@*List) $\endgroup$ – wuyudi Mar 19 at 15:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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