Quel est le meilleur moyen (le meilleur comme de manière conventionnelle) de vérifier si tous les éléments d'une liste sont uniques?
Mon approche actuelle en utilisant un Counter
est:
>>> x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
>>> counter = Counter(x)
>>> for values in counter.itervalues():
if values > 1:
# do something
Puis-je faire mieux?
Pas le plus efficace, mais simple et concis:
if len(x) > len(set(x)):
pass # do something
Cela ne fera probablement pas une grande différence pour les listes restreintes.
Voici une ligne à deux qui fera également la sortie prématurée:
>>> def allUnique(x):
... seen = set()
... return not any(i in seen or seen.add(i) for i in x)
...
>>> allUnique("ABCDEF")
True
>>> allUnique("ABACDEF")
False
Si les éléments de x ne sont pas hashable, vous devrez alors utiliser une liste pour seen
:
>>> def allUnique(x):
... seen = list()
... return not any(i in seen or seen.append(i) for i in x)
...
>>> allUnique([list("ABC"), list("DEF")])
True
>>> allUnique([list("ABC"), list("DEF"), list("ABC")])
False
Une solution de sortie précoce pourrait être
def unique_values(g):
s = set()
for x in g:
if x in s: return False
s.add(x)
return True
cependant, dans les cas les plus rares ou si la sortie anticipée n'est pas le cas le plus courant, je m'attendrais à ce que len(x) != len(set(x))
soit la méthode la plus rapide.
pour la vitesse:
import numpy as np
x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
np.unique(x).size == len(x)
Pourquoi ne pas ajouter toutes les entrées à un ensemble et en vérifier la longueur?
len(set(x)) == len(x)
Alternative à set
, vous pouvez utiliser un dict
.
len({}.fromkeys(x)) == len(x)
Une autre approche entièrement, en utilisant trié et groupby:
from itertools import groupby
is_unique = lambda seq: all(sum(1 for _ in x[1])==1 for x in groupby(sorted(seq)))
Cela nécessite une sorte, mais se termine à la première valeur répétée.
Voici une fonction de sortie précoce récursive:
def distinct(L):
if len(L) == 2:
return L[0] != L[1]
H = L[0]
T = L[1:]
if (H in T):
return False
else:
return distinct(T)
C'est assez rapide pour moi sans utiliser d'étranges conversions (lentes) tout en ayant une approche fonctionnelle.
Voici un O récursif (N2) version pour le plaisir:
def is_unique(lst):
if len(lst) > 1:
return is_unique(s[1:]) and (s[0] not in s[1:])
return True
Que dis-tu de ça
def is_unique(lst):
if not lst:
return True
else:
return Counter(lst).most_common(1)[0][1]==1
Utilisation d'une approche similaire dans un Pandas dataframe pour vérifier si le contenu d'une colonne contient des valeurs uniques:
if tempDF['var1'].size == tempDF['var1'].unique().size:
print("Unique")
else:
print("Not unique")
Pour moi, c'est instantané sur une variable int dans une dateframe contenant plus d'un million de lignes.
Vous pouvez utiliser la syntaxe de Yan (len (x)> len (set (x))), mais au lieu de set (x), définissez une fonction:
def f5(seq, idfun=None):
# order preserving
if idfun is None:
def idfun(x): return x
seen = {}
result = []
for item in seq:
marker = idfun(item)
# in old Python versions:
# if seen.has_key(marker)
# but in new ones:
if marker in seen: continue
seen[marker] = 1
result.append(item)
return result
et faites len (x)> len (f5 (x)). Ce sera rapide et préservera également les commandes.
Le code provient de: http://www.peterbe.com/plog/uniqifiers-benchmark