2011-10-11 4 views
9

Мне нужно сравнить два списка правил формы var -> integer о факте несоответствия.
Чтобы определить, существуют ли какие-либо правила то же самое по lhs и разные по rhs.Как сравнить два списка правил?

Например:

{а-> 3, b-> 1, C-> 4} ~ ??? ~ {a-> 3, b-> 1, c-> 4} = true
{a-> 3, b-> 1, c-> 4} ~ ??? ~ {А-> 3, b-> 2, C-> 4} = FALSE
{а-> 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

В моем случае они уже отсортированные по LHS и все л.ш. уникальны, если это может помочь сделать как простая функция как возможно.

UPD: забыл одну вещь! Списки могут иметь разную длину. Но похоже, что все три текущих ответа остаются в силе.

ответ

7

Вот еще одно решение:

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} 

(Это зависит от того, что списки опций уже отсортирован.)

+0

В дополнение к размеру, это решение в 3 раза быстрее по моим данным, чем другие два. – Nakilon

+0

@Nakilon Если скорость является проблемой, оберните правила на r.h.s. из '/ .' в' Dispatch' - это должно ускорить код, как для моей версии, так и для @ Heike. –

7

Вы могли бы сделать что-то вроде

check[{a__Rule}, {b__Rule}] := 
Module[{common = Intersection[{a}[[All, 1]], {b}[[All, 1]]]}, 
    SameQ[common /. {a}, common /. {b}]] 

Тогда

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

урожайности

True 
False 
False 
+0

+1 Это именно тот подход, который я придумал (но через полчаса после вас!). – DavidC

+0

+1 Это решение может быть легко обобщено для пустых наборов правил, заменив 'BlankSequence' (' __') на 'BlankNullSequence' (' ___ '):' check [{a ___ Rule}, {b___Rule}]: = ... '. –

+0

Какая разница между 'check [{a__Rule}, {b__Rule}]: =' и 'check [a, b]: ='? – Nakilon

7

Возможно проще

check[a : {__Rule}, b : {__Rule}] := SameQ @@ Transpose[a /. b /. a /. Rule -> List] 

EDIT

Вот еще более эзотерическая версия, которая имеет преимущество быть полностью на высоком уровне, в том смысле, что нам не нужно ничего знать о внутренней структуре правил, только как они действуют:

checkAlt[a : {__Rule}, b : {__Rule}] := # === (# /. #) &[a /. b /. a] 

EDIT 2

Ну, позвольте мне бросить в другой, просто для удовольствия:

check1[{a__Rule}, {b__Rule}] := SameQ @@ ({a, b} /. {{a, b}, {b, a}}) 
+0

+1. Очень умно! Но это решение будет корректно работать только из-за отсутствия пересечений между * l.h.s. * и * r.h.s. * обоих наборов правил. В этом смысле решение Хайке является простым (и гораздо легче для понимания). –

+0

Я еще не понимаю, как, но он работает с той же скоростью и успехом, что и прямое решение Хайке. – Nakilon

+0

Умный, мне потребовался момент, чтобы понять, что вы делаете, и построить 'a /. b /. a /. Правило -> Список' сбивало с толку. Но он касается случая, когда правила правил отличаются между двумя списками. – rcollyer

2

Вот несколько обобщенный подход:

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} 

Это один не требует элементов, чтобы быть правила, они могут быть списки, или почти любой другой руководитель. Он также должен работать на любом количестве входных данных.

+0

+1 - Хорошее обобщение. –

Смежные вопросы