What is the correct way to use specific rule for specific pattern match when parsing an expression?
Just define a new function that could take different inputs, either through overloading or using If
, Which
, or Switch
.
Clear[f]
f[x_. Power[z, e_.]] := {x, e}
f[Times[x_, Power[z, e_.]]] := {x, e}
f[x_] := {x, 0}
Cases[lis, y : Alternatives[x_., x_. Power[z, e_.], Times[x_, Power[z, e_.]]] :> f[y]]
(* {{6, 0}, {1, -4}, {4, -2}, {4, 2}, {1, 4}} *)
Update: Below is the most general way I could think of to achieve what the OP wants while still using Cases
.
HoldPattern
is needed to prevent z^0
from evaluating before it is matched. FreeQ
is needed to make sure that the matched coefficient is free from z
**:
Clear[coeff, z]
(* Applies to plus expressions *)
coeff[expr_Plus] :=
Cases[expr, HoldPattern[(c : _?(FreeQ[#, z] &) : 1) (zVar : z^e_. : z^0)] :> {c, e}]
(* Applies to standalone expressions: nest them in a list first before using Cases *)
coeff[expr_] :=
Cases[{expr}, HoldPattern[(c : _?(FreeQ[#, z] &) : 1) (zVar : z^e_. : z^0)] :> {c, e}]
{#, coeff@#} & /@ {1, z, -z, 1/z, 1 + z^-1, 1/z^3 + 3/z + 3 z + z^3, 6 + 1/z^4 + 4/z^2 + 4 z^2 + z^4} //
Grid[Prepend[#, {"expr", "coeff[expr]"}], Frame -> All] &
**
Otherwise things like this might happen:
Cases[{z^2}, HoldPattern[(c : _ : 1) (zVar : z^e_. : z^0)] :> {c, e}]
(* {{z^2, 0}} *)
That's because z^2
matches the first term, while z^0
matches the second term. This is not what we want, which is 1
for the first term, and z^2
for the second term.
One possibility is to use Replace
with Sow
/Reap
:
Scan[
Replace[#, {
x_. Power[z, e_.] :> Sow[{x, e}],
Times[x_, Power[z, e_.]] :> Sow[{x, e}],
x_ :> Sow[{x, 0}]}] &,
lis] // Reap // #[[-1, -1]] &
{{6, 0}, {1, -4}, {4, -2}, {4, 2}, {1, 4}}
However, the wildcard x_
could be tricky if you needed to operate deeper in the expression.
It seems like there should be a way to use Cases
and insert Sow
inside Condition
(/;
) but I have not managed to get that approach working. Maybe someone else can figure it out :)
Another possibility is to use ReplaceAll
on the rhs of RuleDelayed
in the second argument of Cases
:
rules = Alternatives[x_. Power[z, e_.] :> {x, e}, Times[x_, Power[z, e_.]] :> {x, e},
x_. :> {x, 0}]; (* your prefered second argument for Cases *)
Cases[lis, pat : rules[[All, 1]] :> (pat /. List @@ rules)]
(* {{6, 0}, {1, -4}, {4, -2}, {4, 2}, {1, 4}} *)
Update:
exp = {1, z, -z, 1/z, 1 + z^-1, 1/z^3 + 3/z + 3 z + z^3, 6 + 1/z^4 + 4/z^2 + 4 z^2 + z^4};
cF = Cases[If[Head[#] === Plus, #, {#}],
pat : rules[[All, 1]] :> (pat /. List @@ rules)] & (* thanks: @algohi *)
Grid[{{"expr", "cF[expr]"}, ## & @@ ({#, cF@#} & /@ exp)}, Frame -> All]