Функция уникальных значений python

Checking if all elements in a list are unique

What is the best way (best as in the conventional way) of checking whether all elements in a list are unique? My current approach using a Counter is:

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

18 Answers 18

Not the most efficient, but straight forward and concise:

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

Probably won’t make much of a difference for short lists.

Not necessarily, that will execute the body of the conditional if the list has repeating elements (the «#do something» in the example).

For those worried about efficiency with long lists, this is efficient for long lists that are actually unique (where all elements need checking). Early exit solutions take longer (roughly 2x longer in my tests) for actually unique lists. So. if you expect most of your lists to be unique, use this simple set length checking solution. If you expect most of your lists to NOT be unique, use an early exit solution. Which one to use depends on your use case.

This answer is nice. However, let’s be careful here: len(x) > len(set(x)) is True when the elements in x are NOT unique. This question’s title asks exactly the opposite: «Checking if all elements in a list are unique»

Here is a two-liner that will also do early exit:

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

If the elements of x aren’t hashable, then you’ll have to resort to using a list for 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 

@paul-mcguire: Would you be willing to license this code snippet under an Apache 2.0-compatible license (e.g., Apache 2, 2/3-line BSD, MIT, X11, zlib). I’d like to use it in an Apache 2.0 project I’m using, and because StackOverflow’s licensing terms are fubar, I’m asking you as the original author.

I’ve put out other code using MIT license, so that works for me for this snippet. Anything special I need to do?

Читайте также:  Java heap space error code

An early-exit solution could be

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

however for small cases or if early-exiting is not the common case then I would expect len(x) != len(set(x)) being the fastest method.

You can shorten this by putting the following line after s = set() . return not any(s.add(x) if x not in s else True for x in g)

Could you explain why you would expect len(x) != len(set(x)) to be faster than this if early-exiting is not common? Aren’t both operations O(len(x))? (where x is the original list)

Oh, I see: your method is not O(len(x)) because you check if x in s inside of the O(len(x)) for loop.

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

How about adding all the entries to a set and checking its length?

Alternative to a set , you can use a dict .

Another approach entirely, using sorted and groupby:

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

It requires a sort, but exits on the first repeated value.

Came here to post the same solution using groupby and found this answer. I find this most elegant, since this a single expression and works with the built-in tools without requiring any extra variable or loop-statement.

If your list contains arbitrary objects which are not sortable, you can use the id() function to sort them as this is a prerequisite for groupby() to work: groupby(sorted(seq), key=id)

Here is a recursive O(N 2 ) version for fun:

def is_unique(lst): if len(lst) > 1: return is_unique(s[1:]) and (s[0] not in s[1:]) return True 

I’ve compared the suggested solutions with perfplot and found that

is indeed the fastest solution. If there are early duplicates in the list, there are some constant-time solutions which are to be preferred.

enter image description here

enter image description here

Code to reproduce the plot:

import perfplot import numpy as np import pandas as pd def len_set(lst): return len(lst) == len(set(lst)) def set_add(lst): seen = set() return not any(i in seen or seen.add(i) for i in lst) def list_append(lst): seen = list() return not any(i in seen or seen.append(i) for i in lst) def numpy_unique(lst): return np.unique(lst).size == len(lst) def set_add_early_exit(lst): s = set() for item in lst: if item in s: return False s.add(item) return True def pandas_is_unique(lst): return pd.Series(lst).is_unique def sort_diff(lst): return not np.any(np.diff(np.sort(lst)) == 0) b = perfplot.bench( setup=lambda n: list(np.arange(n)), title="All items unique", # setup=lambda n: [0] * n, # title="All items equal", kernels=[ len_set, set_add, list_append, numpy_unique, set_add_early_exit, pandas_is_unique, sort_diff, ], n_range=[2**k for k in range(18)], xlabel="len(lst)", ) b.save("out.png") b.show() 

Источник

Читайте также:  Замена подстроки питон решение

Как получить уникальные элементы списка python

Предположим, есть список, который содержит повторяющиеся числа:

Но нужен список с уникальными числами:

Есть несколько вариантов, как можно получить уникальные значения. Разберем их.

Вариант №1. Использование множества (set) для получения элементов

Использование множества ( set ) — один из вариантов. Он удобен тем, что включает только уникальные элементы. После этого множество можно обратно превратить в список.

Посмотрим на два способа использования множества и списка. Первый — достаточно подробный, но он позволяет увидеть происходящее на каждом этапе.

 
numbers = [1, 2, 2, 3, 3, 4, 5]

def get_unique_numbers(numbers):
list_of_unique_numbers = []
unique_numbers = set(numbers)

for number in unique_numbers:
list_of_unique_numbers.append(number)

return list_of_unique_numbers

print(get_unique_numbers(numbers))

Разберем, что происходит на каждом этапе. Есть список чисел numbers . Передаем его в функцию get_unique_numbers .

Внутри этой функции создается пустой список, который в итоге будет включать все уникальные числа. После этого используется set для получения уникальных чисел из списка numbers .

 
unique_numbers = set(numbers)

В итоге имеется перечень из уникальных чисел. Осталось сделать из него список. Для этого можно использовать цикл, перебирая каждый из элементов.

 
for number in unique_numbers:
list_of_unique_numbers.append(number)

На каждой итерации текущее число добавляется в список list_of_unique_numbers . Наконец, именно этот список возвращается в конце программы.

Есть и более короткий способ использования множества для получения уникальных значений в Python. О нем и пойдет речь дальше.

Короткий вариант с set

Весь код выше можно сжать в одну строку с помощью встроенных в Python функций.

 
numbers = [1, 2, 2, 3, 3, 4, 5]
unique_numbers = list(set(numbers))
print(unique_numbers)

Хотя этот код сильно отличается от первого примера, идея та же. Сперва множество используется для получения уникальных значений. После этого множество превращается в список.

 
unique_numbers = list(set(numbers))

Проще всего думать «изнутри наружу» при чтении этого кода. Самый вложенный код выполняется первым: set(numbers) . Затем — внешний блок: list(set(numbers)) .

Вариант №2. Использование цикла for

Также стоит рассмотреть подход с использованием цикла.

Для начала нужно создать пустой список, который будет включать уникальные числа. После этого можно задействовать цикл для итерации по каждому числу в переданном списке. Если число из него есть в уникальном, то можно переходить к следующему элементу. В противном случае — добавить это число.

Рассмотрим два способа использования цикла. Начнем с более подробного.

 
numbers = [20, 20, 30, 30, 40]

def get_unique_numbers(numbers):
unique = []

for number in numbers:
if number in unique:
continue
else:
unique.append(number)
return unique

print(get_unique_numbers(numbers))

Вот что происходит на каждом этапе. Сначала есть список чисел numbers . Он передается в функцию get_unique_numbers .

Внутри этой функции создается пустой список unique . В итоге он будет включать все уникальные значения.

Цикл будет использоваться для перебора по числам в списке numbers .

 
for number in numbers:
if number in unique:
continue
else:
unique.append(number)

Условные конструкции в цикле проверяют, есть ли число текущей итерации в списке unique . Если да, то цикл переходит на следующую итерации. Если нет — число добавляется в список.

Важно отметить, что добавляются только уникальные числа. Когда цикл завершен, список unique с уникальными числами возвращается.

Короткий способ с циклом

Есть и другой способ использования варианта с циклом, который короче на несколько строк.

 
numbers = [20, 20, 30, 30, 40]

def get_unique_numbers(numbers):
unique = []
for number in numbers:
if number not in unique:
unique.append(number)
return unique

Разница в условной конструкции. В этот раз она следующая — если числа нет в unique , то его нужно добавить.

 
if number not in unique:
unique.append(number)

В противном случае цикл перейдет к следующему числу в списке numbers .

Результат будет тот же. Но иногда подобное читать сложнее, когда булево значение опускается.

Есть еще несколько способов поиска уникальных значений в списке Python. Но достаточно будет тех, которые описаны в этой статье.

Обучение с трудоустройством

Я создал этот блог в 2018 году, чтобы распространять полезные учебные материалы, документации и уроки на русском. На сайте опубликовано множество статей по основам python и библиотекам, уроков для начинающих и примеров написания программ.

Python Q CEO Pythonru admin@pythonru.com https://secure.gravatar.com/avatar/b16f253879f7349f64830c64d1da4415?s=96&d=mm&r=g CEO Pythonru Python Александр Редактор https://t.me/cashncarryhttps://pythonru.com/https://yandex.ru/q/profile/cashnc/ PythonRu.com admin@pythonru.com Alex Zabrodin 2018-10-26 Online Python, Programming, HTML, CSS, JavaScript

Источник

Оцените статью