Je veux faire quelque chose de similaire à ceci:
>>> x = [1,2,3,4,5,6,7,8,9,0]
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> y = [1,3,5,7,9]
>>> y
[1, 3, 5, 7, 9]
>>> y - x # (should return [2,4,6,8,0])
Mais cela n'est pas pris en charge par les listes python Quelle est la meilleure façon de le faire?
Réponses:
Utilisez une compréhension de liste:
Si vous souhaitez utiliser la
-
syntaxe infixe, vous pouvez simplement faire:vous pouvez ensuite l'utiliser comme:
Mais si vous n'avez pas absolument besoin des propriétés de liste (par exemple, la commande), utilisez simplement des ensembles comme les autres réponses le recommandent.
la source
list
pour les noms de variables car il masque lelist
constructeur. Si vous utilisez «liste», veuillez le faire précéder d'un trait de soulignement. De plus, en supprimant le*
, vous avez cassé mon code ...[1,1,2,2] - [1,2]
vous obtiendrez une liste vide.[1,1,2,2] - [2]
donne[1,1]
Donc ce n'est pas vraiment une soustraction de liste, c'est plus comme "Liste de la liste X sans éléments de l'ensemble Y " .y
en unset
avant chaque vérification (ce qui est un coût similaire au travail original). Vous devez soit faire enyset = set(y)
dehors de listcomp, puis testerif item not in yset
, ou, en tant que hack flagrant, faire[item for yset in [set(y)] for item in x if item not in yset]
qui abuse des listcomps imbriqués pour le mettre en cacheyset
comme une ligne. Une solution un-liner un peu moins laide qui fonctionne correctement serait à utiliserlist(itertools.filterfalse(set(y).__contains__, x))
car l'argument tofilterfalse
n'est construit qu'une seule fois.Utiliser la différence définie
Ou vous pouvez simplement avoir des ensembles x et y afin de ne pas avoir à faire de conversions.
la source
TypeError: unhashable type: 'dict'
Il s'agit d'une opération de "soustraction d'ensemble". Utilisez la structure de données définie pour cela.
En Python 2.7:
Production:
la source
si les articles en double et les commandes posent problème:
[i for i in a if not i in b or b.remove(i)]
la source
O(m * n)
exécution (et je grince des dents chaque fois qu'un listcomp inclut des effets secondaires); vous pouvez l'améliorer en utilisantcollections.Counter
pour obtenir l'O(m + n)
exécution.Pour de nombreux cas d'utilisation, la réponse que vous souhaitez est:
Il s'agit d'un hybride entre la réponse d' Aaronasterling et la réponse de QuantumSoup .
La version de aaronasterling fait des
len(y)
comparaisons d'éléments pour chaque élément dansx
, donc cela prend du temps quadratique. La version de quantumSoup utilise des ensembles, elle effectue donc une seule recherche d'ensemble à temps constant pour chaque élément dansx
- mais, comme elle convertit les deuxx
ety
en ensembles, elle perd l'ordre de vos éléments.En convertissant uniquement
y
en un ensemble et en itérantx
dans l'ordre, vous obtenez le meilleur des deux mondes: le temps linéaire et la préservation de l'ordre. *Cependant, cela a toujours un problème avec la version de quantumSoup: cela nécessite que vos éléments soient lavables. C'est à peu près intégré dans la nature des ensembles. ** Si vous essayez, par exemple, de soustraire une liste de dict d'une autre liste de dict, mais que la liste à soustraire est grande, que faites-vous?
Si vous pouvez décorer vos valeurs de manière à ce qu'elles soient lavables, cela résout le problème. Par exemple, avec un dictionnaire plat dont les valeurs sont elles-mêmes hachables:
Si vos types sont un peu plus compliqués (par exemple, vous avez souvent affaire à des valeurs compatibles JSON, qui sont hachables, ou à des listes ou des codes dont les valeurs sont récursivement du même type), vous pouvez toujours utiliser cette solution. Mais certains types ne peuvent tout simplement pas être convertis en quelque chose de lavable.
Si vos articles ne sont pas, et ne peuvent pas être, lavables, mais ils sont comparables, vous pouvez au moins obtenir un temps log-linéaire (
O(N*log M)
, ce qui est beaucoup mieux que leO(N*M)
temps de la solution de liste, mais pas aussi bon que leO(N+M)
temps de la solution réglée) en triant et en utilisantbisect
:Si vos articles ne sont ni lavables ni comparables, alors vous êtes coincé avec la solution quadratique.
* Notez que vous pouvez également le faire en utilisant une paire d'
OrderedSet
objets, pour laquelle vous pouvez trouver des recettes et des modules tiers. Mais je pense que c'est plus simple.** La raison pour laquelle les recherches définies sont à temps constant est qu'il suffit de hacher la valeur et de voir s'il existe une entrée pour ce hachage. S'il ne peut pas hacher la valeur, cela ne fonctionnera pas.
la source
La recherche de valeurs dans des ensembles est plus rapide que leur recherche dans des listes:
Je pense que cela évoluera légèrement mieux que:
Les deux préservent l'ordre des listes.
la source
set(y)
et ne pas se convertiry
en un nouvel ensemble sur chaque boucle? Sinon, vous feriez la réponse de besoin abarnert:ys = set(y); [i for i in x if i not in ys]
.if i not in set(y)
prend 25% de plus queif i not in y
(oùy
est une liste). La pré-conversion de l'ensemble prend 55% moins de temps. Testé avec assez courtx
ety
, mais les différences devraient être plus prononcées avec la longueur, le cas échéant.y
pour chaque élément dex
; à moins que la comparaison d'égalité ne soit vraiment coûteuse par rapport au calcul de hachage, cela sera toujours perdu en clairitem not in y
.Si les listes autorisent les éléments en double, vous pouvez utiliser Counter à partir de collections:
Si vous devez conserver l'ordre des éléments de x:
la source
Counter.subtract
ne supprime pas les éléments à valeur nulle (-
et le-=
fait, mais passubtract
), vous ne cesserez donc jamais de supprimer des éléments. Vous souhaitez remplacernot v in c
parnot c[v]
(qui renvoie zéro pour les éléments inexistants, vous pouvez donc tester en toute sécurité le retour pour "zéro" vianot
).Je pense que la façon la plus simple d'y parvenir est d'utiliser set ().
la source
Les autres solutions ont l'un des problèmes suivants:
x = [1, 2, 2, 2]
ety = [2, 2]
ils se convertissenty
en aset
, et suppriment tous les éléments correspondants (en laissant[1]
uniquement) ou en supprimant un de chaque élément unique (en partant[1, 2, 2]
), lorsque le comportement correct consiste à supprimer2
deux fois, partir[1, 2]
, ouO(m * n)
fonctionnent, où une solution optimale peutO(m + n)
fonctionnerAlain était sur la bonne voie
Counter
pour résoudre les problèmes n ° 2 et n ° 3, mais cette solution perdra son ordre. La solution qui préserve l'ordre (en supprimant les premièresn
copies de chaque valeur pour lesn
répétitions dans leslist
valeurs à supprimer) est:Essayez-le en ligne!
Pour lui faire supprimer les dernières copies de chaque élément, changez simplement la
for
boucle enfor val in reversed(x):
et ajoutezout.reverse()
immédiatement après avoir quitté lafor
boucle.La construction de l'
Counter
estO(n)
en termes dey
« lien de, itérerx
estO(n)
en termes dex
» longueur s, et lesCounter
tests d'adhésion et de mutation sontO(1)
, toutlist.append
est amortiO(1)
(une donnéeappend
peut êtreO(n)
, mais pour beaucoup deappend
s, les moyennes Big-O globalO(1)
depuis moins en moins d'entre eux nécessitent une réaffectation), de sorte que le travail global effectué l'estO(m + n)
.Vous pouvez également tester pour déterminer s'il y avait des éléments
y
qui n'ont pas été supprimésx
en testant:la source
int
s dans un tableau de longueur fixe) ou doit faire plus que leO(m + n)
travail (par exemple , la meilleure grande -O serait de faire un trilist
de paires valeur / nombre uniques, en transformant lesO(1)
dict
recherches en recherchesO(log n)
binaires; vous auriez besoin de valeurs uniques avec leurs nombres, pas seulement des valeurs non uniques triées, car sinon vous paieriez desO(n)
frais pour supprimer le éléments du trilist
).Essaye ça.
la source
La réponse fournie par @aaronasterling semble bon, cependant, il est compatible avec l'interface par défaut de la liste:
x = MyList(1, 2, 3, 4)
vsx = MyList([1, 2, 3, 4])
. Ainsi, le code ci-dessous peut être utilisé comme une liste plus conviviale pour python:Exemple:
la source
Je pense que c'est plus rapide:
la source
Cet exemple soustrait deux listes:
la source