Вопрос-Ответ

Converting a list to a set changes element order

Преобразование списка в набор изменяет порядок элементов

Недавно я заметил, что при преобразовании a list в set порядок элементов изменяется и сортируется по символам.

Рассмотрим этот пример:

x=[1,2,20,6,210]
print(x)
# [1, 2, 20, 6, 210] # the order is same as initial order

set(x)
# set([1, 2, 20, 210, 6]) # in the set(x) output order is sorted

Мои вопросы -


  1. Почему это происходит?

  2. Как я могу выполнять операции set (особенно set difference) без потери первоначального порядка?

Переведено автоматически
Ответ 1

  1. A set - это неупорядоченная структура данных, поэтому порядок вставки не сохраняется.


  2. Это зависит от ваших требований. Если у вас есть обычный список, и вы хотите удалить некоторый набор элементов, сохранив порядок списка, вы можете сделать это с пониманием списка:


    >>> a = [1, 2, 20, 6, 210]
    >>> b = set([6, 20, 1])
    >>> [x for x in a if x not in b]
    [2, 210]

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


    >>> a = dict.fromkeys([1, 2, 20, 6, 210])
    >>> b = dict.fromkeys([6, 20, 1])
    >>> dict.fromkeys(x for x in a if x not in b)
    {2: None, 210: None}

    b на самом деле здесь не нужно упорядочивать – вы также можете использовать set. Обратите внимание, что a.keys() - b.keys() возвращает разницу в наборе как set, поэтому порядок вставки не сохраняется.


    В более старых версиях Python вы можете использовать collections.OrderedDict вместо:


    >>> a = collections.OrderedDict.fromkeys([1, 2, 20, 6, 210])
    >>> b = collections.OrderedDict.fromkeys([6, 20, 1])
    >>> collections.OrderedDict.fromkeys(x for x in a if x not in b)
    OrderedDict([(2, None), (210, None)])

Ответ 2

В Python 3.6 set() теперь следует сохранить порядок, но есть другое решение для Python 2 и 3:

>>> x = [1, 2, 20, 6, 210]
>>> sorted(set(x), key=x.index)
[1, 2, 20, 6, 210]
Ответ 3

Удалите дубликаты и сохраните порядок с помощью функции ниже

def unique(sequence):
seen = set()
return [x for x in sequence if not (x in seen or seen.add(x))]

Как удалить дубликаты из списка, сохранив порядок в Python

Ответ 4

Отвечая на ваш первый вопрос, набор - это структура данных, оптимизированная для операций с наборами. Как и математический набор, он не навязывает и не поддерживает какой-либо определенный порядок элементов. Абстрактная концепция набора не обеспечивает соблюдения порядка, поэтому реализация этого не требуется. Когда вы создаете набор из списка, Python имеет право изменять порядок элементов для нужд внутренней реализации, которую он использует для набора, которая способна эффективно выполнять операции с набором.

python