Sembra che l'OP si occupasse solo del caso di due variabili, ma poiché StackOverflow è anche per coloro che cercano la stessa domanda in seguito, proverò ad affrontare il caso generico qui in dettaglio; Una risposta precedente contiene già una risposta generica usando itertools.permutations()
, ma quel metodo porta a O(N*N!)
confronti, poiché ci sono N!
permutazioni con N
elementi ciascuno. (Questa è stata la motivazione principale per questa risposta)
Innanzitutto, riassumiamo come alcuni dei metodi delle risposte precedenti si applicano al caso generico, come motivazione per il metodo presentato qui. Userò A
per fare riferimento (x, y)
e B
fare riferimento a (a, b)
, che può essere tuple di lunghezza arbitraria (ma uguale).
set(A) == set(B)
è veloce, ma funziona solo se i valori sono hash e puoi garantire che una delle tuple non contenga valori duplicati. (Ad esempio {1, 1, 2} == {1, 2, 2}
, come sottolineato da @ user2357112 nella risposta di @Daniel Mesejo)
Il metodo precedente può essere esteso per funzionare con valori duplicati usando dizionari con conteggi, anziché set: (Questo ha ancora la limitazione che tutti i valori devono essere hash, quindi ad esempio valori mutabili come list
non funzioneranno)
def counts(items):
d = {}
for item in items:
d[item] = d.get(item, 0) + 1
return d
counts(A) == counts(B)
sorted(A) == sorted(B)
non richiede valori hash, ma è leggermente più lento e richiede invece valori ordinabili. (Quindi ad es. complex
Non funzionerà)
A in itertools.permutations(B)
non richiede valori hash o ordinabili, ma come già accennato, ha O(N*N!)
complessità, quindi anche con solo 11 articoli, può richiedere più di un secondo per terminare.
Quindi, c'è un modo per essere il più generale, ma lo fa considerevolmente più veloce? Perché sì, controllando "manualmente" che c'è la stessa quantità di ogni articolo: (La complessità di questo è O(N^2)
, quindi non va bene nemmeno per input di grandi dimensioni; Sulla mia macchina, 10k articoli possono richiedere un secondo, ma con input più piccoli, come 10 elementi, questo è veloce come gli altri)
def unordered_eq(A, B):
for a in A:
if A.count(a) != B.count(a):
return False
return True
Per ottenere le migliori prestazioni, si potrebbe desiderare di provare dict
prima il metodo basato su, tornare al sorted
metodo basato su se ciò fallisce a causa di valori non lavabili, e infine ritornare al count
metodo basato su se anche quello fallisce a causa di valori non ordinabili.
x,y, a,b
: sono ints / float / stringhe, oggetti arbitrari o cosa? Se fossero dei tipi predefiniti ed è stato possibile mantenere entrambix,y
ea,b
in ordine, è possibile evitare il secondo ramo. Si noti che la creazione di un set causerà l'x,y, a,b
hash di ciascuno dei quattro elementi , che potrebbe essere o meno banale o avere un impatto sulle prestazioni a seconda del tipo di oggetti che sono.