Самые популярные ответы - O (N) (хорошо! -), но, как указывают @Paul и @Mark, они требуют, чтобы элементы списка были хэшируемыми. Предложенные @Paul и @Mark подходы к непригодным для употребления предметам носят общий характер, но принимают O (N в квадрате), т. Е. Много.
Если элементы вашего списка не являются хэшируемыми, но сопоставимы , вы можете добиться большего ... вот подход, который всегда работает настолько быстро, насколько это возможно, учитывая природу элементов списка.
import itertools
def allunique(L):
# first try sets -- fastest, if all items are hashable
try:
return len(L) == len(set(L))
except TypeError:
pass
# next, try sort -- second fastest, if items are comparable
try:
L1 = sorted(L)
except TypeError:
pass
else:
return all(len(list(g))==1 for k, g in itertools.groupby(L1))
# fall back to the slowest but most general approach
return all(v not in L[i+1:] for i, L in enumerate(L))
Это O (N), где это возможно (все элементы хешируемы), O (N log N) как наиболее частый запасной вариант (некоторые элементы не подлежат изменению, но все сопоставимы), O (N в квадрате), где это неизбежно (некоторые элементы не подлежат проверке, например, диктанты и некоторые несопоставимые, например, комплексные числа).
Вдохновение для этого кода происходит от старого рецепта великого Тима Питерса, который отличался тем, что фактически создавал список уникальных предметов (а также был так давно, что set
не было рядом - он должен был использовать dict
...! -), но в основном столкнулись с идентичными проблемами.