web-dev-qa-db-fra.com

Vérifier si tous les éléments d'une liste sont uniques

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?

86
user225312

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.

142
yan

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
87
PaulMcG

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.

21
6502

pour la vitesse:

import numpy as np
x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
np.unique(x).size == len(x)
12
locojay

Pourquoi ne pas ajouter toutes les entrées à un ensemble et en vérifier la longueur?

len(set(x)) == len(x)
10
Grzegorz Oledzki

Alternative à set, vous pouvez utiliser un dict.

len({}.fromkeys(x)) == len(x)
9
Tugrul Ates

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.

2
PaulMcG

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.

2
mhourdakis

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
2
Karol

Que dis-tu de ça

def is_unique(lst):
    if not lst:
        return True
    else:
        return Counter(lst).most_common(1)[0][1]==1
1
yilmazhuseyin

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.

1
user1718097

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

0
canisrufus