The pattern for a direct replacement proves to be a bit tricky:
start = g[1] + g[2] + g[3] + g[1]*g[3] + 3*g[1]*g[2] + 6*g[1]*g[2]*g[3];
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[1] + g[2] + g[3] + g[1]*g[3] + 3*g[1]*g[2] + 6*g[1]*g[2]*g[3]]
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[1] + g[2] + g[3] + g[1]*g[3] + 3*g[1]*g[2] + 6*g[1]*g[2]*g[3]
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}}