Как сделать списки, содержащие только отдельные элементы в Python?

У меня есть список в Python, как я могу сделать его значения уникальными?

10 ответов

Решение

Самое простое - преобразовать в набор, а затем обратно в список:

my_list = list(set(my_list))

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

Модифицированные версии http://www.peterbe.com/plog/uniqifiers-benchmark

Чтобы сохранить заказ:

def f(seq): # Order preserving
  ''' Modified version of Dave Kirby solution '''
  seen = set()
  return [x for x in seq if x not in seen and not seen.add(x)]

Хорошо, теперь, как это работает, потому что это немного сложно здесь if x not in seen and not seen.add(x):

In [1]: 0 not in [1,2,3] and not print('add')
add
Out[1]: True

Почему он возвращает True? print (и set.add) ничего не возвращает:

In [3]: type(seen.add(10))
Out[3]: <type 'NoneType'>

а также not None == True, но:

In [2]: 1 not in [1,2,3] and not print('add')
Out[2]: False

Почему он печатает "добавить" в [1], но не в [2]? Увидеть False and print('add'), и не проверяет второй аргумент, потому что он уже знает ответ и возвращает истину, только если оба аргумента истинны.

Более общая версия, более читаемая, на основе генератора, добавляет возможность преобразовывать значения с помощью функции:

def f(seq, idfun=None): # Order preserving
  return list(_f(seq, idfun))

def _f(seq, idfun=None):  
  ''' Originally proposed by Andrew Dalke '''
  seen = set()
  if idfun is None:
    for x in seq:
      if x not in seen:
        seen.add(x)
        yield x
  else:
    for x in seq:
      x = idfun(x)
      if x not in seen:
        seen.add(x)
        yield x

Без заказа (это быстрее):

def f(seq): # Not order preserving
  return list(set(seq))

Однострочник и сохранение порядка

list(OrderedDict.fromkeys([2,1,1,3]))

хотя тебе понадобится

from collections import OrderedDict

Позвольте мне объяснить вам на примере:

если у вас есть список Python

>>> randomList = ["a","f", "b", "c", "d", "a", "c", "e", "d", "f", "e"]

и вы хотите удалить дубликаты из него.

>>> uniqueList = []

>>> for letter in randomList:
    if letter not in uniqueList:
        uniqueList.append(letter)

>>> uniqueList
['a', 'f', 'b', 'c', 'd', 'e']

Вот как вы можете удалить дубликаты из списка.

Чтобы сохранить заказ:

l = [1, 1, 2, 2, 3]
result = list()
map(lambda x: not x in result and result.append(x), l)
result
# [1, 2, 3]

Как насчет словарного понимания?

>>> mylist = [3, 2, 1, 3, 4, 4, 4, 5, 5, 3]

>>> {x:1 for x in mylist}.keys()
[1, 2, 3, 4, 5]

РЕДАКТИРОВАТЬ@ комментарий Дэнни: мое первоначальное предложение не держит ключи в порядке. Если вам нужно отсортировать ключи, попробуйте:

>>> from collections import OrderedDict

>>> OrderedDict( (x,1) for x in mylist ).keys()
[3, 2, 1, 4, 5]

который сохраняет элементы в порядке первого появления элемента (не проверено)

Характеристики наборов в Python состоят в том, что элементы данных в наборе неупорядочены и дубликаты не допускаются. Если вы попытаетесь добавить элемент данных в набор, который уже содержит элемент данных, Python просто проигнорирует его.

>>> l = ['a', 'a', 'bb', 'b', 'c', 'c', '10', '10', '8','8', 10, 10, 6, 10, 11.2, 11.2, 11, 11]
>>> distinct_l = set(l)
>>> print(distinct_l)
set(['a', '10', 'c', 'b', 6, 'bb', 10, 11, 11.2, '8'])

Если все элементы списка могут использоваться в качестве словарных ключей (то есть все они могут быть хэшируемыми), это часто происходит быстрее. FAQ по программированию на Python

d = {}
for x in mylist:
    d[x] = 1
mylist = list(d.keys())

Самый простой способ удалить дубликаты при сохранении порядка - это использовать collection.OrderedDict (Python 2.7+).

from collections import OrderedDict
d = OrderedDict()
for x in mylist:
    d[x] = True
print d.iterkeys()

С http://www.peterbe.com/plog/uniqifiers-benchmark:

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
Другие вопросы по тегам