Finding rules with Cases

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?

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"}

-Jeff

FilterRules was made for this type of thing, but it is keyed off matches on the left hand side

Reverse/@FilterRules[Reverse/@set1, "green"]