设置更改元素顺序?
最近我注意到,当我转换列表来设置顺序或元素被改变,并按字符sorting。
考虑这个例子:
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
,而应该使用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)])
注意
b
的顺序并不重要,所以它可以是任何可迭代的,但它应该是一个支持O(1)成员testing的迭代。
编辑 :上面的答案假定你希望能够对所有发生的集合执行(sorting)集合操作,特别是对以前的集合操作的结果。 如果这不是必要的,你可以简单地使用列表的一些集合,并为其他人设置,例如
>>> a = [1, 2, 20, 6, 210] >>> b = set([6, 20, 1]) >>> [x for x in a if x not in b] [2, 210]
这失去了b
的顺序,不允许对a
和结果进行快速的成员testing。 集允许快速的会员资格testing,并列出订单。 如果您需要同一个集合中的这两个function,请使用collections.OrderedDict
。
回答你的第一个问题,set是一个针对set操作进行优化的数据结构,并且像math集合一样,它不强制/维护任何特定的元素顺序。 集合的抽象概念不强制执行,所以不执行。 当你从一个列表创build一个集合时,python会自由地改变元素的顺序,以满足它为一个集合所使用的内部实现的需求,这个集合能够高效地执行集合操作。
在Python 3.6中, set()
现在应该保持顺序,但Python 2和Python 3还有另外一个解决scheme:
>>> x = [1, 2, 20, 6, 210] >>> sorted(set(x), key=x.index) [1, 2, 20, 6, 210]
如其他答案中所表示的,集合是不保留元素顺序的数据结构(和math概念)
但是,通过使用集合和词典的组合,您可以实现您想要的function – 尝试使用以下代码片段:
# 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
build立在斯文的答案上,我发现使用collections.OrderedDict像这样帮助我完成了你想要的任务,并允许我在字典中添加更多的项目:
import collections x=[1,2,20,6,210] z=collections.OrderedDict.fromkeys(x) z OrderedDict([(1, None), (2, None), (20, None), (6, None), (210, None)])
如果你想添加项目,但仍然像一个集合,你可以做:
z['nextitem']=None
你可以在字典上执行像z.keys()这样的操作并获取该集合:
z.keys() [1, 2, 20, 6, 210]
这是一个简单的方法来做到这一点:
x=[1,2,20,6,210] print sorted(set(x))