1
$\begingroup$

Edit: I am matching and replacing a particular expression. At the same time... I want to store matched variables for later use. I got it to work with messed up code involving Block. Is there a smarter way to do this?

(*Initialize*)
variables = {}; expr = f[x] + g[x] + 3 f[y];

(*now match and replace, and storing the argument into "variables"*)
expr /. f[x_] :> Block[{}, variables = Union[variables, {x}]; fNew[x]]

Now if I type:

variables
(*output is {x,y}*)

I get the desired output.

The empty {} inside Block makes me feel I'm doing this in a kludgy way... (feel free to improve any other parts of the code too!)

$\endgroup$
4
  • $\begingroup$ And what to do for f[] or f[x,y] ? $\endgroup$
    – hieron
    Commented Aug 17, 2014 at 20:18
  • $\begingroup$ f[] and f[x,y] do not match. $\endgroup$
    – QuantumDot
    Commented Aug 17, 2014 at 20:32
  • $\begingroup$ but f[g[x]] should match? $\endgroup$
    – hieron
    Commented Aug 17, 2014 at 20:43
  • $\begingroup$ yes f[g[x]] that should match. $\endgroup$
    – QuantumDot
    Commented Aug 17, 2014 at 21:21

3 Answers 3

4
$\begingroup$

Sow and Reap:

{result, variables} = Reap[
  expr /. f[x_] :> fNew[Sow@x]
  ]
variables
(* Out: {{x, y}} *)

In your original solution you do not need Block:

variables = {};
expr /. f[x_] :> (variables = Union[variables, {x}]; fNew[x])

And AppendTo can make your code shorter:

variables = {};
expr /. f[x_] :> (AppendTo[variables, x]; fNew[x])

When collecting many different values such that it may become a performance issue the Sow and Reap solution is recommended in the documentation and elsewhere. Compared to your code the alternatives do not delete duplicates, you can do this afterwards with DeleteDuplicates.

$\endgroup$
2
  • 1
    $\begingroup$ Sow? Reap? So we're farmers now?! Nice solution. I'll wait for more answers/comments before accepting this one $\endgroup$
    – QuantumDot
    Commented Aug 17, 2014 at 21:00
  • 1
    $\begingroup$ @QuantumDot For what it's worth I would also use Sow and Reap, but I would not put Sow inside fNew as I would not assume that it will evaluate (fNew might hold its arguments). I would use: expr /. f[x_] :> (Sow @ x; fNew @ x) $\endgroup$
    – Mr.Wizard
    Commented Aug 18, 2014 at 3:09
0
$\begingroup$
variables = Union@Cases[expr, f[x__] :> x, {0, Infinity}]
(* {x, y} *)
$\endgroup$
2
  • 2
    $\begingroup$ Does this give the replaced expr as output? I should have said that outputting the replaced expr is needed, and I also need to store the variables on the side. $\endgroup$
    – QuantumDot
    Commented Aug 17, 2014 at 20:30
  • $\begingroup$ expr /. f[x_] :> fNew[x]. I'm not quite sure what's the usefulness of combining both steps (replacement and getting variables) into one, but @Pickett's Sow and Reap do the job very nicely. $\endgroup$
    – seismatica
    Commented Aug 17, 2014 at 20:53
0
$\begingroup$

another version

Clear@"`*"
variables = {};
expr = f[x] + g[x] + 3 f[y] + f[x + y] f[x];
var[x_] := CompoundExpression[variables = variables~Join~{x}, x]

(* usage *)
expr /. f[x_] :> fNew@var@x
variables

(* out *)
fNew[x] + 3 fNew[y] + fNew[x] fNew[x + y] + g[x]
{x, y, x, x + y}
$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.