How to extract parts of an expression using Cases
One part of the problem has already been mentioned by @C.E. in his answer: Since Association
is seen as atomic by the pattern matcher, no insertion of matched expressions happens within it.
The reason this is a problem at all is that your postproc
is not actually evaluated after the matches have been identified, but before. To prevent evaluation of the right side of the replacement rule before the match has been found, you can use RuleDelayed
(:>
)
With[
{syms = syms},
Cases[exprs, # :> postproc[syms], Infinity] & /@ patts
]
(* {
{<|"x1" -> 14, "x2" -> x2, "y" -> y|>},
{<|"x1" -> x1, "x2" -> 12, "y" -> 3|>, <|"x1" -> x1, "x2" -> 2, "y" -> 8|>}
} *)
Note the use of With
to insert the value of syms
into the now held right side of the rule (if syms
were to be evaluated after the match is found, nothing would be inserted, since x1
, x2
, etc. need to be literally present in the replacement).
A possible workaround:
keys = ToString /@ syms;
postproc[x_, h_: keys] := Thread[h -> x]
Association @@@ Cases[exprs, # -> postproc[syms], Infinity] & /@ patts
{{<|"x1" -> 14, "x2" -> x2, "y" -> y|>}, {<|"x1" -> x1, "x2" -> 12,
"y" -> 3|>, <|"x1" -> x1, "x2" -> 2, "y" -> 8|>}}