# Collect term in a distributive way

Consider

P = x (a2 b2 v^a2-1+a3 b3 v^a3-1+d1+d2-2 y)-(y-d1)(y-d2)-x


I would like to collect terms in (x,y,z) in a distributive way, that is to get an expression of the form:

$$P=\sum_{p} f_p(a2,b2,a3,b3,d1,d2)\; x^{i_p}y^{j_p}v^{k_p}$$

I tried:

Total@MonomialList[P, {x, y, v}]


and

FromCoefficientRules[CoefficientRules[P, {x, y, v}],{x, y, v}]


without success.

The issue is that MonomialList and friends only work if the variables have integer powers, and so v^a2, for instance, is a problem.

Update

Another way, with pattern matching and Collect:

Collect[P, Times @@@ Rest@Subsets@{x^(_ : 1), y^(_ : 1), v^(_ : 1)}]


Original Solution

Here's hack that's a little ugly but should generally work:

Total@Module[{i = 2, rule},
rule = Thread[# -> (# /. v^_ :> v^i++)] &@Cases[P, v^_, Infinity];
MonomialList[P /. rule, {x, y, v}] /. Reverse /@ rule
]
(* -d1 d2 + (-3 + d1 + d2) x + a2 b2 v^a2 x + a3 b3 v^a3 x + (d1 + d2) y - 2 x y - y^2 *)


The point is to replace any instance of v^(something) with a unique v^(integer), make the replacement v^(something) -> v^(integer) in the expression, construct the desired expression using Total@MonomialList, and then undoing the replacement.

You can use code something like this:

((P // Expand) /. {
(t_.) x^(i_.)  v^(j_.) -> t T[x^i  v^j] ,
(t_.) x^(i_.)  y^(j_.) -> t T[x^i  y^j] ,
(t_.) x^(i_.) -> t T[x^i] ,
(t_.) y^(i_.) -> t T[y^i]} //
FullSimplify) /. T -> Identity // InputForm


which returns

 -(d1*d2) + (-3 + d1 + d2)*x + a2*b2*v^a2*x +
a3*b3*v^a3*x + (d1 + d2)*y - 2*x*y - y^2