Message Boards Message Boards


Finding rules with Cases

Posted 9 years ago
9 Replies
20 Total Likes
I'm trying to process a list of rules. I'm trying to find specific rules inside of Cases, but it keeps turning everything into the value I'm trying to find. I want it to return the whole rule. For example:
set1 = {"tree1" -> "green", "tree2" -> "red", "tree3" -> "green",
   "tree4" -> "orange", "tree5" -> "orange", "tree6" -> "red",
   "tree7" -> "green", "tree8" -> "red", "tree9" -> "orange",
   "tree10" -> "dead"};
Cases[set1, _ -> "green"]
Any advice?
9 Replies
Cases with a Rule for a second argument has a special meaning, so you need to tweak your usage a bit. One possibility is:
Cases[set1, HoldPattern[_ -> "green"]]
This should do it:
Cases[set1, HoldPattern[_ -> "green"]]
{"tree1" -> "green", "tree3" -> "green", "tree7" -> "green"}
One approach could be to do the following:
In[19]:= Cases[set1, (x_Rule /; Last[x] === "green")]
Out[19]= {"tree1" -> "green", "tree3" -> "green", "tree7" -> "green"}
 Since Cases allows one to replace a pattern via this form:
Cases[{e1, ...}, pattern->rhs]
You could wrap the pattern in HoldPattern so it knows that you aren't trying to do a recplacement:
In[20]:= Cases[set1, HoldPattern[_ -> "green"]]
Out[20]= {"tree1" -> "green", "tree3" -> "green", "tree7" -> "green"}
Using Select[] is an alternative sometimes:
In[1]:= set1 = {"tree1" -> "green", "tree2" -> "red",
"tree3" -> "green", "tree4" -> "orange", "tree5" -> "orange",
"tree6" -> "red", "tree7" -> "green", "tree8" -> "red",
"tree9" -> "orange", "tree10" -> "dead"};

In[2]:= Select[set1, Last[#] == "green" &]

Out[2]= {"tree1" -> "green", "tree3" -> "green", "tree7" -> "green"}
Cases[set1, _ -> "green"]
tells Cases to replace expressions matching
(any Mathematica expression) with "green". That is the way Cases works. But what you want is to find cases of occurrence of the pattern
(_ -> "green")
To do this you must use
HoldPattern[_ -> "green"]
which is the same as
_ -> "green"
for pattern matching. There is an example in the "Possible issues" section in the documentation of Cases.

So we get
In[53]:= Cases[set1, HoldPattern[_ -> "green"]]

Out[53]= {"tree1" -> "green", "tree3" -> "green", "tree7" -> "green"}
Here is another approach:

In[1]:= rules = {"tree1" -> "green", "tree2" -> "red",
"tree3" -> "green", "tree4" -> "orange", "tree5" -> "orange",
"tree6" -> "red", "tree7" -> "green", "tree8" -> "red",
"tree9" -> "orange", "tree10" -> "dead"};

In[2]:= Cases[rules, p:(_ -> "red") :> p]
Out[2]= {"tree2" -> "red", "tree6" -> "red", "tree8" -> "red"}
I think you want this:
In[14]:= Cases[set1, HoldPattern[_ -> "green"]]

Out[14]= {"tree1" -> "green", "tree3" -> "green", "tree7" -> "green"}

FilterRules was made for this type of thing, but it is keyed off matches on the left hand side
Reverse/@FilterRules[Reverse/@set1, "green"]
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract