Преобразование списка в набор изменяет порядок элементов
Недавно я заметил, что при преобразовании 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
Мои вопросы -
Почему это происходит?
Как я могу выполнять операции set (особенно set difference) без потери первоначального порядка?
Переведено автоматически
Ответ 1
A set - это неупорядоченная структура данных, поэтому порядок вставки не сохраняется.
Это зависит от ваших требований. Если у вас есть обычный список, и вы хотите удалить некоторый набор элементов, сохранив порядок списка, вы можете сделать это с пониманием списка:
>>> a = [1, 2, 20, 6, 210] >>> b = set([6, 20, 1]) >>> [x for x in a if x notin 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 notin b) {2: None, 210: None}
b на самом деле здесь не нужно упорядочивать – вы также можете использовать set. Обратите внимание, что a.keys() - b.keys() возвращает разницу в наборе как set, поэтому порядок вставки не сохраняется.
>>> 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 notin b) OrderedDict([(2, None), (210, None)])
Ответ 2
В Python 3.6 set() теперь следует сохранить порядок, но есть другое решение для Python 2 и 3:
Отвечая на ваш первый вопрос, набор - это структура данных, оптимизированная для операций с наборами. Как и математический набор, он не навязывает и не поддерживает какой-либо определенный порядок элементов. Абстрактная концепция набора не обеспечивает соблюдения порядка, поэтому реализация этого не требуется. Когда вы создаете набор из списка, Python имеет право изменять порядок элементов для нужд внутренней реализации, которую он использует для набора, которая способна эффективно выполнять операции с набором.