Extract function arguments

Is there a way to extract the arguments of a function? Consider the following example:

I have this sum

g + g + g + g*g + 3*g*g + 6*g*g*g

Now, what I want to do is exctract the function arguments and apply them to another function func which takes the arguments as a list.

func[{1}] + func[{2}] + func[{3}] + func[{1, 3}] + 3*func[{1, 2}] + 6*func[{1, 2, 3}]

I know there is Extract[g*g, Position[g*g, _Integer]] but that does not work if I have a multiplicative constant.

Is there a way to do this?

The pattern for a direct replacement proves to be a bit tricky:

start = g + g + g + g*g + 3*g*g + 6*g*g*g;

start /. y__g z_g | y__g x_. :> x func[Join @@ List @@@ {y, z}]
func[{1}] + func[{2}] + func[{3}] + 3 func[{1, 2}] + func[{1, 3}] + 6 func[{1, 2, 3}]

If order doesn't matter, and arguably it shouldn't with Times you could use:

start //. g[x__] g[y__] :> g[x, y] /. g[x__] :> func[{x}]
func[{1}] + func[{2}] + func[{3}] + 3 func[{1, 2}] + func[{1, 3}] + 6 func[{3, 1, 2}]

The OP asked how to extract just the arguments of g and do so preserving the order of the input. This requires wrapping the expression in Hold (or similar) before it is evaluated, to prevent the automatic sorting of Plus. I shall use a variation of kguler's cleaner patten, and Cases since we want only parts of the expression and not the entire thing transformed. I shall scan at level 2 (rather than the default level 1) to bypass the additional Head.

start2 = Hold[g + g + g + g*g + 3*g*g + 6*g*g*g]

Cases[start2, (x___ : 1) p__g :> First /@ {p}, {2}]
{{1}, {2}, {3}, {1, 3}, {1, 2}, {1, 2, 3}}

Let me take this opportunity to show an unusual but potentially useful method I also used for Convert head Times to List. You can hold your expression unevaluated by using SetDelayed, but normally it is fully evaluated when it is called. (This has the advantage of letting you use the expression elsewhere without additional effort such as ReleaseHold.) To get around that when doing the extraction you can Block the functions that you do not want to evaluate during the call. Example:

start3 := g + g + g + g*g + 3*g*g + 6*g*g*g

Block[{Plus},
Cases[start3, (x___ : 1) p__g :> First /@ {p}]
]
{{1}, {2}, {3}, {1, 3}, {1, 2}, {1, 2, 3}}

Alternatively, you could use my step evaluator function to get the unevaluated expression wrapped in HoldForm, then use level 2 again:

Cases[step @ start3, (x___ : 1) p__g :> First /@ {p}, {2}]
{{1}, {2}, {3}, {1, 3}, {1, 2}, {1, 2, 3}}
• Wizard! Thanks, the first solution really helps me. Do u maybe know how to get just the arguments in a list: just {{1},{2},{3},{1,2},{1,3},{1,2,3}} like in the example? – rainer Mar 14 '13 at 18:49
• @rainer I don't know why you say "like in the example" as your example is clearly the form that I show in my answer. If however you want the argument-only list you could do: Cases[start, (x___ : 1) p__g :> First /@ {p}] (based on kguler's answer). Note that the output is not in the same order that you show because the terms are automatically sorted by Plus before Cases even sees them. If that is a problem you will need to define start using Hold. Ask if you need help. – Mr.Wizard Mar 14 '13 at 19:08
• thank you. yes just the argument-only list, but I need it to be in the same order. How can I use 'Hold' here? – rainer Mar 14 '13 at 21:13
• @rainer I added several examples that I hope you will find of use and interest. – Mr.Wizard Mar 15 '13 at 1:18

Would this do, or does the ordering matter?

Clear@func
func /: func[a_] func[b_] := func[Flatten@{a, b}]
g + g + g + g*g + 3*g*g + 6*g*g*g/. g[a_] -> func[{a}]

Use ReplaceAll (/.)

g + g + g + g*g + 3*g*g + 6*g*g*g /. g -> func
func + func + 3 func func + func + func func
+ 6 func func func

Edit

g + g + g + g*g + 3*g*g + 6*g*g*g /. {
g[a_]*g[b_]*g[c_] -> func[{a, b, c}], g[a_]*g[b_] -> func[{a, b}], g[a_] -> func[{a}]}
func[{1}] + func[{2}] + func[{3}] + 3 func[{1, 2}] + func[{1, 3}] + 6 func[{1, 2, 3}]
• thanks,I figured that out already, but thats not exactly what I want to do: I want to transform e.g.6*g*g*g into 6*func[{1,2,3}] – rainer Mar 12 '13 at 10:25
• @rainer Like Cases[6*g*g*g, g[x_] -> x, 2] ? – b.gates.you.know.what Mar 12 '13 at 10:44
• @Mr.Wizard Thanks for pointing out what the OP wanted, your solution is elegant +1. – Artes Mar 12 '13 at 11:23
• Thanks for the vote. I wonder if the question is intended to be more general than the example given. Are the functions Plus and Times arbitrary? – Mr.Wizard Mar 12 '13 at 11:24
expr = g + g + g + g*g + 3*g*g + 6*g*g*g;
expr /. Times[x___:1 , p__g] :> x func[{p}[[All, 1]]]
(* func[{1}] + func[{2}] + func[{3}] + 3 func[{1, 2}] + func[{1, 3}] + 6 func[{1, 2, 3}]*)
• I had almost the same: expr /. Times[a___ : 1, x : __g] :> a func@Join@x /. g -> List – Simon Woods Mar 13 '13 at 10:07
• @Simon, just noticed that i could save a character using __g instead of ___g :) – kglr Mar 13 '13 at 10:46
• I would have sworn I tried that pattern and it didn't work. Anyway, nice work. I hope you don't mind my edit but your code was invalid syntax in v7 and All works for both. – Mr.Wizard Mar 13 '13 at 11:13
• @Mr.Wizard, Thanks for the edit and the vote. – kglr Mar 13 '13 at 11:33