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

想想这个例子:

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

我的问题是

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


当前回答

正如在其他答案中指出的那样,集合是不保留元素顺序的数据结构(和数学概念)

然而,通过使用集合和字典的组合,你可以实现任何你想要的-尝试使用这些片段:

# save the element order in a dict:
x_dict = dict(x,y for y, x in enumerate(my_list) )
x_set = set(my_list)
#perform desired set operations
...
#retrieve ordered list from the set:
new_list = [None] * len(new_set)
for element in new_set:
   new_list[x_dict[element]] = element

其他回答

如果你有少量的元素在你的两个初始列表上,你想做集差操作,而不是使用集合。OrderedDict使实现复杂化,使其可读性较差,您可以使用:

# initial lists on which you want to do set difference
>>> nums = [1,2,2,3,3,4,4,5]
>>> evens = [2,4,4,6]
>>> evens_set = set(evens)
>>> result = []
>>> for n in nums:
...   if not n in evens_set and not n in result:
...     result.append(n)
... 
>>> result
[1, 3, 5]

它的时间复杂度不是很好,但它很简洁,易于阅读。

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

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

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

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

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

有趣的是,人们总是用“现实问题”来开理论科学定义的玩笑。

如果设置有顺序,首先需要解决以下问题。 如果你的列表有重复的元素,当你把它变成一个集合时,顺序应该是什么?如果我们合并两个集合,顺序是什么?如果我们在相同的元素上相交两个不同顺序的集合是什么顺序?

另外,set在搜索特定键时要快得多,这在set操作中非常好(这就是为什么你需要set,而不是list)。

如果您真的关心索引,只需将其保存为列表即可。如果您仍然想对许多列表中的元素执行set操作,最简单的方法是为每个具有相同键的列表创建一个字典,并创建一个list值,其中包含原始列表中键的所有索引。

def indx_dic(l):
    dic = {}
    for i in range(len(l)):
        if l[i] in dic:
            dic.get(l[i]).append(i)
        else:
            dic[l[i]] = [i]
    return(dic)

a = [1,2,3,4,5,1,3,2]
set_a  = set(a)
dic_a = indx_dic(a)

print(dic_a)
# {1: [0, 5], 2: [1, 7], 3: [2, 6], 4: [3], 5: [4]}
print(set_a)
# {1, 2, 3, 4, 5}

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

unique_list=[]

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

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