How to compare two lists of rules?
I need to compare two Lists of Rules of form var -> integer
on the fact of mismatch.
For example:
{a->3, b->1, c->4} ~ ??? ~ {a->3, b->1, c->4} = true
{a->3, b->1, c->4} ~ ??? ~ {a->3, b->2, c->4} = false {a->3, b->1, c->4} ~ ??? ~ {a->1, b->3, c->4} = false {a->3, b->1, c->4} ~ ??? ~ {c->4, d->8, e->9} = true {a->3, b->1, c->4} ~ ??? ~ {d->8, e->9, f->7} = true
In my case they are already sorted by lhs and all lhs are unique if it coul开发者_开发百科d help to make as simple function as possible.
UPD: forgot one thing! Lists can be of different length. But seems like all three current answers are still valid.
Here's another solution:
In[12]:= check[a:{__Rule}, b:{__Rule}] := FilterRules[a, b] === FilterRules[b, a]
In[18]:= {{a -> 3, b -> 1, c -> 4}~check ~ {a -> 3, b -> 1, c -> 4} ,
{a -> 3, b -> 1, c -> 4}~check ~ {a -> 3, b -> 2, c -> 4},
{a -> 3, b -> 1, c -> 4}~check ~ {a -> 1, b -> 3, c -> 4},
{a -> 3, b -> 1, c -> 4}~check ~ {c -> 4, d -> 8, e -> 9},
{a -> 3, b -> 1, c -> 4}~check ~ {d -> 8, e -> 9, f -> 7}}
Out[18]= {True, False, False, True, True}
(This relies on the fact that the lists of options are already sorted.)
You could do something like
check[{a__Rule}, {b__Rule}] :=
Module[{common = Intersection[{a}[[All, 1]], {b}[[All, 1]]]},
SameQ[common /. {a}, common /. {b}]]
Then
check[{a -> 3, b -> 1, c -> 4}, {a -> 3, b -> 1, c -> 4}]
check[{a -> 3, b -> 1, c -> 4}, {a -> 3, b -> 2, c -> 4}]
check[{a -> 3, b -> 1, c -> 4}, {a -> 1, b -> 3, c -> 4}]
yields
True
False
False
Perhaps simpler
check[a : {__Rule}, b : {__Rule}] := SameQ @@ Transpose[a /. b /. a /. Rule -> List]
EDIT
Here is an even more esoteric version, which has the advantage of being completely high-level, in the sense that we don't need to know anything about the internal structure of the rules, only how they act:
checkAlt[a : {__Rule}, b : {__Rule}] := # === (# /. #) &[a /. b /. a]
EDIT 2
Well, let me throw in another one, just for fun:
check1[{a__Rule}, {b__Rule}] := SameQ @@ ({a, b} /. {{a, b}, {b, a}})
Here's a slightly generalized approach:
In[24]:= check[lists__] :=
And @@ (SameQ @@@ GatherBy[Join[lists], First])
In[25]:= {
{a -> 3, b -> 1, c -> 4}~check~{a -> 3, b -> 1, c -> 4},
{a -> 3, b -> 1, c -> 4}~check~{a -> 3, b -> 2, c -> 4},
{a -> 3, b -> 1, c -> 4}~check~{a -> 1, b -> 3, c -> 4},
{a -> 3, b -> 1, c -> 4}~check~{c -> 4, d -> 8, e -> 9},
{a -> 3, b -> 1, c -> 4}~check~{d -> 8, e -> 9, f -> 7}
}
Out[25]= {True, False, False, True, True}
This one doesn't require the elements to be rules, they could be lists, or pretty much any other head. It should also work on any number of inputs.
精彩评论