Per molti casi d'uso, la risposta che desideri è:
ys = set(y)
[item for item in x if item not in ys]
Questo è un ibrido tra la risposta di aaronasterling e la risposta di quantumSoup .
La versione di aaronasterling len(y)confronta gli elementi per ogni elemento in x, quindi richiede un tempo quadratico. La versione di quantumSoup utilizza set, quindi esegue una singola ricerca di set a tempo costante per ogni elemento in x—ma, poiché converte entrambi x e yin set, perde l'ordine dei tuoi elementi.
Convertendo solo yin un set e ripetendo xin ordine, ottieni il meglio da entrambi i mondi: tempo lineare e conservazione dell'ordine. *
Tuttavia, questo ha ancora un problema dalla versione di quantumSoup: richiede che i tuoi elementi siano hash. È praticamente integrato nella natura dei set. ** Se stai provando, ad esempio, a sottrarre un elenco di dadi da un altro elenco di dadi, ma l'elenco da sottrarre è grande, cosa fai?
Se riesci a decorare i tuoi valori in qualche modo che sono hash, questo risolve il problema. Ad esempio, con un dizionario semplice i cui valori sono essi stessi cancellabili:
ys = {tuple(item.items()) for item in y}
[item for item in x if tuple(item.items()) not in ys]
Se i tuoi tipi sono un po 'più complicati (ad esempio, spesso hai a che fare con valori compatibili con JSON, che sono hash, o elenchi o dicts i cui valori sono ricorsivamente dello stesso tipo), puoi comunque usare questa soluzione. Ma alcuni tipi non possono essere convertiti in nulla di hash.
Se i tuoi articoli non sono, e non possono essere realizzati, hash, ma sono comparabili, puoi almeno ottenere un tempo log-linear ( O(N*log M)che è molto meglio del O(N*M)tempo della soluzione dell'elenco, ma non buono come il O(N+M)tempo della soluzione impostata) ordinando e utilizzando bisect:
ys = sorted(y)
def bisect_contains(seq, item):
index = bisect.bisect(seq, item)
return index < len(seq) and seq[index] == item
[item for item in x if bisect_contains(ys, item)]
Se i tuoi articoli non sono né lavabili né confrontabili, allora sei bloccato con la soluzione quadratica.
* Nota che puoi anche farlo usando una coppia di OrderedSetoggetti, per i quali puoi trovare ricette e moduli di terze parti. Ma penso che sia più semplice.
** Il motivo per cui le ricerche impostate sono a tempo costante è che tutto ciò che deve fare è hash il valore e vedere se c'è una voce per quell'hash. Se non è possibile eseguire l'hashing del valore, questo non funzionerà.