5
$\begingroup$

If I have a list of rules associated with indexed variables like:

solution = {a[1] -> 1, a[2] -> 10, a[3] -> 100}

I would like to be able to extract all of the values associated with the rules. Although this problem is simple with a small number of variables, I am not sure how to generalize it.

For instance, I can use pattern matching to obtain 1 and 10, respectively:

a[1]/.solution
a[2]/.solution

However, I can't seem to generalize this to extract a[n] values from a list of rules. What is proper pattern to do this?

$\endgroup$
0

2 Answers 2

5
$\begingroup$

This is not what Rules are made for but the following works well for simple cases:

solution[[All, 2]]
{1, 10, 100}

More "proper" way:

a /@ Range[3] /. solution

or equivalent suggested by Mr. Wizard

Array[a, 3] /. solution

For more nested list of rules you can use Cases (but then you have to keep an eye on what is what ;)) :

Cases[solution, (a[_] -> x_):> x, Infinity]
{1, 10, 100}

Or the same but in different form:

Cases[solution, Rule[a[_], x_] :> x, Infinity]
Cases[solution, HoldPattern[a[_] -> x_] :> x, Infinity]

Remarks about Cases:

  • For your example, default levelspec for Cases, which is {1}, will do the job.
  • ReplaceAll (/.) will work with solution containing Rule (->) or RuleDelayed (:>) but for Cases we have to point this out:

solution = {a[1] -> 1, a[2] :> 5, a[3] -> 100}

Cases[solution, Rule[a[_], x_] :> x]
Cases[solution, (Rule | RuleDelayed)[a[_], x_] :> x]
{a[1] -> 1, a[2] :> 5, a[3] -> 100}
{1, 100}
{1, 5, 100}
$\endgroup$
5
  • $\begingroup$ Great answer. I usually use e.g. Array[a, 3] myself, FWIW. You might want to address the possibility of :> rules in your Cases methods. $\endgroup$
    – Mr.Wizard
    Commented Aug 26, 2013 at 21:27
  • $\begingroup$ @Mr.Wizard Thank you. I saw this question and I've thought it is going to be closed, but I've failed looking for duplicate or extension example in documentation. (I'm afraid to ask but what do you mean by your second remark?) $\endgroup$
    – Kuba
    Commented Aug 26, 2013 at 21:33
  • 1
    $\begingroup$ What if e.g. solution = {a[1] -> 1, a[2] :> $var, a[3] -> 100} -- it would be good to at least mention that this won't be handled by the pattern Rule[a[_], x_] :> x. By the way I notice you're using HoldPattern; if it is only for grouping you could use parentheses as well. $\endgroup$
    – Mr.Wizard
    Commented Aug 26, 2013 at 21:45
  • 1
    $\begingroup$ Why not just solution /. (a[_] -> x_) :> x => {1, 10, 100}? $\endgroup$
    – user1066
    Commented Aug 26, 2013 at 23:26
  • $\begingroup$ @TomD Good point, that's similar to Cases but simpler in form, you may add this example as an answer too :) $\endgroup$
    – Kuba
    Commented Aug 26, 2013 at 23:39
4
$\begingroup$

Kuba already posted the natural ways to approach this problem, so here is an unnatural one.

You can temporarily (inside a Block) make the rules definitions for the Symbol a by setting DownValues:

rules =
 {a[1]->76,a[2]->36,a[3]->87,a[4]->42,a[5]->52,a[6]->73,a[7]->41,a[8]->58,a[9]->79};

Block[{a}, DownValues[a] = rules; Array[a, 5]]
{76, 36, 87, 42, 52}
$\endgroup$

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.