Je cherche un moyen simple (et rapide) de déterminer si deux listes non numérotées contiennent les mêmes éléments:
Par exemple:
['one', 'two', 'three'] == ['one', 'two', 'three'] : true
['one', 'two', 'three'] == ['one', 'three', 'two'] : true
['one', 'two', 'three'] == ['one', 'two', 'three', 'three'] : false
['one', 'two', 'three'] == ['one', 'two', 'three', 'four'] : false
['one', 'two', 'three'] == ['one', 'two', 'four'] : false
['one', 'two', 'three'] == ['one'] : false
J'espère pouvoir le faire sans utiliser de carte.
Python a un type de données intégré pour une collection non ordonnée de choses (pouvant être remplies), appelée set
. Si vous convertissez les deux listes en ensembles, la comparaison sera non ordonnée.
_set(x) == set(y)
_
EDIT: @mdwhatcott indique que vous souhaitez vérifier les doublons. set
les ignore, vous avez donc besoin d'une structure de données similaire qui garde également une trace du nombre d'éléments dans chaque liste. Ceci s'appelle un multiset ; la meilleure approximation dans la bibliothèque standard est un collections.Counter
:
_>>> import collections
>>> compare = lambda x, y: collections.Counter(x) == collections.Counter(y)
>>>
>>> compare([1,2,3], [1,2,3,3])
False
>>> compare([1,2,3], [1,2,3])
True
>>> compare([1,2,3,3], [1,2,2,3])
False
>>>
_
Si les éléments sont toujours presque triés comme dans votre exemple, alors la fonction .sort()
( timsort ) devrait être rapide:
>>> a = [1,1,2]
>>> b = [1,2,2]
>>> a.sort()
>>> b.sort()
>>> a == b
False
Si vous ne voulez pas trier sur place, vous pouvez utiliser sorted()
.
En pratique, il pourrait toujours être plus rapide que collections.Counter()
(malgré le fait que O(n)
soit asymptotiquement meilleur que le O(n*log(n))
pour .sort()
). Mesure le; Si c'est important.
sorted(x) == sorted(y)
Copier à partir d'ici: Vérifier si deux listes non ordonnées sont égales
Je pense que c'est la meilleure réponse à cette question parce que
Vous voulez voir s'ils contiennent les mêmes éléments, mais ne vous souciez pas de la commande.
Vous pouvez utiliser un ensemble:
>>> set(['one', 'two', 'three']) == set(['two', 'one', 'three'])
True
Mais l'objet set lui-même ne contiendra qu'une instance de chaque valeur unique et ne préservera pas l'ordre.
>>> set(['one', 'one', 'one']) == set(['one'])
True
Donc, si le suivi des doublons/longueur est important, vous voudrez probablement également vérifier la longueur:
def are_eq(a, b):
return set(a) == set(b) and len(a) == len(b)
si vous ne souhaitez pas utiliser la bibliothèque de collections, vous pouvez toujours faire quelque chose comme ceci: étant donné que a
et b
sont vos listes, les éléments suivants renvoient le nombre d'éléments correspondants (il tient compte de l'ordre) .
sum([1 for i,j in Zip(a,b) if i==j])
Donc,
len(a)==len(b) and len(a)==sum([1 for i,j in Zip(a,b) if i==j])
sera True
si les deux listes sont identiques, contiennent les mêmes éléments et dans le même ordre. False
sinon.
Vous pouvez donc définir la fonction de comparaison comme pour la première réponse ci-dessus, mais sans la bibliothèque de collections.
compare = lambda a,b: len(a)==len(b) and len(a)==sum([1 for i,j in Zip(a,b) if i==j])
et
>>> compare([1,2,3], [1,2,3,3])
False
>>> compare([1,2,3], [1,2,3])
True
>>> compare([1,2,3], [1,2,4])
False
Une réponse à la question ci-dessus est la suivante: -
laissez les deux listes être list1 et list2, et votre exigence est de vous assurer que deux listes comportent les mêmes éléments, puis, selon moi, voici la meilleure approche: -
if ((len(list1) == len(list2)) and
(all(i in list2 for i in list1))):
print 'True'
else:
print 'False'
Le code ci-dessus fonctionnera selon vos besoins, c'est-à-dire si tous les éléments de list1 sont dans list2 et vice-verse.
Mais si vous voulez juste vérifier si tous les éléments de list1 sont présents dans list2 ou non, alors vous devez utiliser le code ci-dessous uniquement: -
if all(i in list2 for i in list1):
print 'True'
else:
print 'False'
La différence est que le dernier imprimera True, si list2 contient des éléments supplémentaires ainsi que tous les éléments de list1. En termes simples, cela garantira que tous les éléments de list1 seront présents dans list2, que list2 comporte ou non des éléments supplémentaires.
Qu'en est-il d'obtenir la représentation sous forme de chaîne des listes et de les comparer?
>>> l1 = ['one', 'two', 'three']
>>> l2 = ['one', 'two', 'three']
>>> l3 = ['one', 'three', 'two']
>>> print str(l1) == str(l2)
True
>>> print str(l1) == str(l3)
False
En supposant que vous sachiez déjà que les listes ont la même taille, les éléments suivants garantiront la valeur True si et seulement si deux vecteurs sont exactement identiques (ordre compris)
functools.reduce(lambda b1,b2: b1 and b2, map(lambda e1,e2: e1==e2, listA, ListB), True)
Exemple:
>>> from functools import reduce
>>> def compvecs(a,b):
... return reduce(lambda b1,b2: b1 and b2, map(lambda e1,e2: e1==e2, a, b), True)
...
>>> compvecs(a=[1,2,3,4], b=[1,2,4,3])
False
>>> compvecs(a=[1,2,3,4], b=[1,2,3,4])
True
>>> compvecs(a=[1,2,3,4], b=[1,2,4,3])
False
>>> compare_vectors(a=[1,2,3,4], b=[1,2,2,4])
False
>>>