7
$\begingroup$

This question already has an answer here:

Consider a set of rules, e.g.

{a -> aa, b -> bb, c -> cc, d -> dd, e -> ee}

I want to remove from this list all patterns of the form e->_ and to do so, I would like to form the Complement of matching patterns in my original set.

However if I use Cases, the description tells us that it has a special meaning, if a rule is given as second argument: The rule is applied to matching patterns after they have been identified.

Cases[{a, b, c, d, e, e}, e -> whow]

returns

{whow, whow}

because without the rule for e, {e,e} would be returned and this is transformed to {whow, whow} according to the given rule.

Now my example given above is such that the pattern to be searched for is a rule, namely

Rule[e,Blank[]]

As the explanation of Cases tells us, if a rule is input a second argument, the rule is applied to the matches. So

Cases[{a -> aa, b -> bb, c -> cc, d -> dd, e -> ee} , 
 Rule[e, Blank[]]]

returns an empty set because there is no match for e (in the set on the left, there is Rule[e,ee], not a pure e without anything around it. If I put Rule[e,Blank[] under Hold, the same happens.

$\endgroup$

marked as duplicate by Kuba, Martin Ender, Alexey Popkov, MarcoB, RunnyKine Apr 11 '16 at 13:35

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

11
$\begingroup$

Under the Possible Issues tab of the Cases documentation.

Use HoldPattern to treat the rule itself as a pattern:

Cases[{a -> aa, b -> bb, c -> cc, d -> dd, e -> ee}, HoldPattern[e -> ee]]
(*{e -> ee}*)
$\endgroup$
1
$\begingroup$
Select[{a -> aa, b -> bb, c -> cc, d -> dd, e -> ee} , 
 MatchQ[#, Rule[e, Blank[]]] &]

returns

{e->ee}

To remove all patterns involving e->_ use

Complement[#, Select[#, MatchQ[#, Rule[e, Blank[]]] &]] &  @  {a -> 
   aa, b -> bb, c -> cc, d -> dd, e -> ee}

Bingo!

After learning about HoldPattern, Verbatim and FilterRules in the siblings of my post (which I did not find before I posted), I constructed something which might be useful for others:

ComplementFilterRules[rules_List, patt_] := 
 Complement[rules, 
  FilterRules[rules, 
   patt]]; (* Exclude patt from a given list of rules: patt may be a 
single pattern or a list of patterns, only the lhs of those influence 
the result *)

and one step ahead in the management of options:

(* like ComplementFilterRules, but add the rules from the pattern and 
finally sort the result *)
OverrideFilterRules[rules_List, patt__ /; Length[{patt}] > 1] := 
 OverrideFilterRules[
  rules, {patt}];  (* the special case with more than 1 option 
argument *)

OverrideFilterRules[rules_List, patt_] := (* the general case *)
 Sort[Flatten[
   Union[Complement[rules, FilterRules[rules, patt]], {patt}]]];

application example:

OverrideFilterRules[{a -> aa, b -> bb,  c -> cc, d -> dd}, {b -> q, 
  d -> ddd}]
{a -> aa, b -> q, c -> cc, d -> ddd}

Thanks for pointing to the duplicates!

$\endgroup$
  • $\begingroup$ Maybe you require something like {a -> aa, b -> bb, c -> cc, d -> dd, e -> ee} /. (e -> _) :> Nothing (or am I missing something obvious)? $\endgroup$ – user1066 Apr 11 '16 at 9:52
  • $\begingroup$ Also, just for fun: FilterRules[yourList, Except[{e -> _}]] == Cases[yourList, Except[e -> _]] == (yourList /. (e -> _) :> Nothing) $\endgroup$ – user1066 Apr 11 '16 at 10:34
  • $\begingroup$ And (OverrideFilterRules[{a -> aa, b -> bb, c -> cc, d -> dd}, {b -> q, d -> ddd}]) == ({a -> aa, b -> bb, c -> cc, d -> dd} /. {(b -> bb) :> (b -> q), (d -> _) :> (d -> ddd) }) $\endgroup$ – user1066 Apr 11 '16 at 20:31

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