开发者

How to compare two lists of rules?

开发者 https://www.devze.com 2023-04-12 00:05 出处:网络
I need to compare two Lists of Rules of form var -> integer on the fact of mismatch. To determine, if there are any rules the same by lhs and different by rhs.

I need to compare two Lists of Rules of form var -> integer on the fact of mismatch.

To determine, if there are any rules the same by lhs and different by rhs.

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消