2011-10-11 4 views
9

Ho bisogno di confrontare due liste di regole del modulo var -> integer sul fatto della mancata corrispondenza.
Per determinare se esistono regole uguali per lhs e diverse per rhs.Come confrontare due elenchi di regole?

Ad esempio:

{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} = falso
{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

Nel mio caso sono già ordinati per LHS e tutti LHS sono unici se potesse contribuire a rendere come funzione semplice possibile.

UPD: dimentica una cosa! Le liste possono essere di lunghezza diversa. Ma sembra che tutte e tre le attuali risposte siano ancora valide.

risposta

7

Ecco un'altra soluzione:

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} 

(Questo si basa sul fatto che le liste delle opzioni sono già ordinati.)

+0

Oltre alle dimensioni, questa soluzione è 3 volte più veloce sui miei dati rispetto agli altri due. – Nakilon

+0

@Nakilon Se la velocità è un problema, avvolgere le regole su r.h.s. di '/ .' in' Dispatch' - questo dovrebbe velocizzare il codice, sia per la mia versione (s) che per quella di @ Heike. –

7

Si potrebbe fare qualcosa di simile

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

Poi

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

rendimenti

True 
False 
False 
+0

+1 Questo è esattamente l'approccio che ho trovato (ma mezz'ora dopo di te!). – DavidC

+0

+1 Questa soluzione può essere facilmente generalizzata per insiemi vuoti di regole sostituendo 'BlankSequence' (' __') con 'BlankNullSequence' (' ___ '):' verifica [{a ___ Rule}, {b___Rule}]: = ... '. –

+0

Che differenza tra 'check [{a__Rule}, {b__Rule}]: =' e 'check [a, b]: ='? – Nakilon

7

Forse più semplice

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

EDIT

Ecco una versione ancora più esoterica, che ha il vantaggio di essere completamente di alto livello, nel senso che non abbiamo bisogno di sapere nulla circa la struttura interna delle regole, solo il modo agiscono:

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

EDIT 2

Beh, mi permetta di gettare in un altro, solo per divertimento:

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

+1. Molto intelligente! Ma questa soluzione funzionerà correttamente solo che non ci sono intersezioni tra * l.h.s. * e * r.h.s. * di entrambi i gruppi di regole. In questo senso, la soluzione di Heike è semplice (e molto più semplice da comprendere). –

+0

Non ho ancora capito come, ma funziona con la stessa velocità e successo della soluzione semplice di Heike. – Nakilon

+0

Intelligente, mi ci è voluto un momento per capire cosa stai facendo, e il costrutto 'a /. b /. a /. Regola -> Elenco era confusa. Ma, si tratta del caso in cui il lhs delle regole differisce tra le due liste. – rcollyer

2

Ecco un approccio leggermente generalizzata:

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} 

Questo non richiede gli elementi per essere regole, potrebbero essere elenchi o praticamente qualsiasi altra testa. Dovrebbe funzionare anche su un numero qualsiasi di input.

+0

+1 - Una buona generalizzazione. –