Проверка, все ли элементы в списке уникальны - PullRequest
85 голосов
/ 11 марта 2011

Каков наилучший способ (лучше, чем обычный способ) проверки того, являются ли все элементы в списке уникальными?

Мой текущий подход с использованием Counter:

>>> x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
>>> counter = Counter(x)
>>> for values in counter.itervalues():
        if values > 1: 
            # do something

Могу ли я сделать лучше?

Ответы [ 13 ]

141 голосов
/ 11 марта 2011

Не самый эффективный, но прямой и лаконичный:

if len(x) > len(set(x)):
   pass # do something

Вероятно, не будет иметь большого значения для коротких списков.

87 голосов
/ 12 марта 2011

Вот две строки, которые также будут выполнять ранний выход:

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

Если элементы x не являются хэшируемыми, вам придется прибегнуть к использованию списка для 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
21 голосов
/ 11 марта 2011

Ранним выходом может быть

def unique_values(g):
    s = set()
    for x in g:
        if x in s: return False
        s.add(x)
    return True

однако для небольших случаев или если ранний выход не является частым случаем, я бы ожидал, что len(x) != len(set(x)) будет самым быстрым методом.

12 голосов
/ 30 ноября 2012

для скорости:

import numpy as np
x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
np.unique(x).size == len(x)
10 голосов
/ 11 марта 2011

Как насчет добавления всех записей в набор и проверки его длины?

len(set(x)) == len(x)
9 голосов
/ 11 марта 2011

Альтернатива set, вы можете использовать dict.

len({}.fromkeys(x)) == len(x)
2 голосов
/ 14 декабря 2014

Вот рекурсивная версия O (N 2 ) для развлечения:

def is_unique(lst):
    if len(lst) > 1:
        return is_unique(s[1:]) and (s[0] not in s[1:])
    return True
2 голосов
/ 28 апреля 2013

Вот рекурсивная функция раннего выхода:

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)    

Это достаточно быстро для меня без использования странных (медленных) преобразований при подходе функционального стиля.

2 голосов
/ 27 декабря 2012

Другой подход целиком, с использованием сортировки и группирования:

from itertools import groupby
is_unique = lambda seq: all(sum(1 for _ in x[1])==1 for x in groupby(sorted(seq)))

Требуется сортировка, но выход по первому повторному значению.

1 голос
/ 20 апреля 2016

Использование аналогичного подхода в фрейме данных Pandas для проверки, содержит ли содержимое столбца уникальные значения:

if tempDF['var1'].size == tempDF['var1'].unique().size:
    print("Unique")
else:
    print("Not unique")

Для меня это происходит мгновенно для переменной int в фрейме даты, содержащем более миллиона строк..

...