最近我注意到,当我转换一个列表来设置元素的顺序是改变的,并按字符排序。

想想这个例子:

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

我的问题是

为什么会这样? 如何才能在不丢失初始顺序的情况下进行设置操作(特别是设置差异)?


当前回答

A set is an unordered data structure, so it does not preserve the insertion order. This depends on your requirements. If you have an normal list, and want to remove some set of elements while preserving the order of the list, you can do this with a list comprehension: >>> a = [1, 2, 20, 6, 210] >>> b = set([6, 20, 1]) >>> [x for x in a if x not in b] [2, 210] If you need a data structure that supports both fast membership tests and preservation of insertion order, you can use the keys of a Python dictionary, which starting from Python 3.7 is guaranteed to preserve the insertion order: >>> 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 doesn't really need to be ordered here – you could use a set as well. Note that a.keys() - b.keys() returns the set difference as a set, so it won't preserve the insertion order. In older versions of Python, you can use collections.OrderedDict instead: >>> 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)])

其他回答

另一种更简单的方法是创建一个空列表,例如“unique_list”,用于从原始列表中添加唯一的元素,例如:

unique_list=[]

for i in original_list:
    if i not in unique_list:
        unique_list.append(i)
    else:
        pass

这将为您提供所有独特的元素,并保持顺序。

删除重复和保存顺序以下功能

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

如何从列表中删除重复,同时保留Python中的顺序

A set is an unordered data structure, so it does not preserve the insertion order. This depends on your requirements. If you have an normal list, and want to remove some set of elements while preserving the order of the list, you can do this with a list comprehension: >>> a = [1, 2, 20, 6, 210] >>> b = set([6, 20, 1]) >>> [x for x in a if x not in b] [2, 210] If you need a data structure that supports both fast membership tests and preservation of insertion order, you can use the keys of a Python dictionary, which starting from Python 3.7 is guaranteed to preserve the insertion order: >>> 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 doesn't really need to be ordered here – you could use a set as well. Note that a.keys() - b.keys() returns the set difference as a set, so it won't preserve the insertion order. In older versions of Python, you can use collections.OrderedDict instead: >>> 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)])

在Python 3.6中,set()现在应该保持顺序,但Python 2和3有另一个解决方案:

>>> x = [1, 2, 20, 6, 210]
>>> sorted(set(x), key=x.index)
[1, 2, 20, 6, 210]

在数学中,有集和有序集(oset)。

set:唯一元素的无序容器(已实现) oset:唯一元素的有序容器

在Python中,只有集合是直接实现的。我们可以用常规字典键(3.7+)来模拟偏移量。

鉴于

a = [1, 2, 20, 6, 210, 2, 1]
b = {2, 6}

Code

oset = dict.fromkeys(a).keys()
# dict_keys([1, 2, 20, 6, 210])

Demo

删除复制,保留插入顺序。

list(oset)
# [1, 2, 20, 6, 210]

字典键上类似set的操作。

oset - b
# {1, 20, 210}

oset | b
# {1, 2, 5, 6, 20, 210}

oset & b
# {2, 6}

oset ^ b
# {1, 5, 20, 210}

细节

注意:无序结构并不排除有序元素。相反,维持秩序并不能得到保证。例子:

assert {1, 2, 3} == {2, 3, 1}                    # sets (order is ignored)

assert [1, 2, 3] != [2, 3, 1]                    # lists (order is guaranteed)

人们可能会很高兴地发现,列表和多集(mset)是两种更迷人的数学数据结构:

list:允许复制的有序元素容器(已实现) mset:允许复制的无序元素容器(NotImplemented)*

总结

Container | Ordered | Unique | Implemented
----------|---------|--------|------------
set       |    n    |    y   |     y
oset      |    y    |    y   |     n
list      |    y    |    n   |     y
mset      |    n    |    n   |     n*  

多重集可以通过collections.Counter()间接模拟,这是一个类似字典的多重度(计数)映射。