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

想想这个例子:

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时,Python可以根据它用于set的内部实现的需要自由地改变元素的顺序,这能够有效地执行set操作。

其他回答

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

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

你可以用一行代码删除重复的值并保持插入的列表顺序,Python 3.8.2

mylist = ['b', 'b', 'a', 'd', 'd', 'c']


results = list({value:"" for value in mylist})

print(results)

>>> ['b', 'a', 'd', 'c']

results = list(dict.fromkeys(mylist))

print(results)

>>> ['b', 'a', 'd', 'c']

上面的最高分概念的实现,将它带回一个列表:

def SetOfListInOrder(incominglist):
    from collections import OrderedDict
    outtemp = OrderedDict()
    for item in incominglist:
        outtemp[item] = None
    return(list(outtemp))

在Python 3.6和Python 2.7上测试(简要)。

迟了,但你可以用熊猫,pd。转换列表,同时保持顺序:

import pandas as pd
x = pd.Series([1, 2, 20, 6, 210, 2, 1])
print(pd.unique(x))

输出: 数组([1,2,20,6,210])

适用于字符串列表

x = pd.Series(['c', 'k', 'q', 'n', 'p','c', 'n'])
print(pd.unique(x))

输出 ['c' 'k' 'q' 'n' 'p']

如果你有少量的元素在你的两个初始列表上,你想做集差操作,而不是使用集合。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]

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