2012-03-20 87 views
42

最近我注意到,當我轉換列表來設置順序或元素更改並按字符排序。設置更改元素順序?

考慮這個例子:

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 

我的問題是 -

  1. 這究竟是爲什麼?
  2. 如何在不丟失初始訂單的情況下設置操作(尤其是設置差異)?
+5

爲什麼不想失去最初的順序,特別是如果你正在執行set操作? 「秩序」對集合來說是一個無意義的概念,不僅僅在Python中,而且在數學中。 – 2012-03-20 18:48:51

+46

@KarlKnechtel - 是「訂單對於數學中的集合是一個無意義的概念」,但是我遇到了現實世界的問題:) – 2012-03-21 11:32:55

回答

50
  1. set是一個無序的數據結構。

  2. 不要使用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)會員資格測試。

編輯:上面的回答假設你希望能夠還對前一組操作的結果對所有發生的集合執行(有序)集合操作,尤其如此。如果這不是必要的,你可以簡單地爲一些集合使用列表,併爲其他集合設置例如

>>> 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,結果快速成員測試。集合允許快速的會員資格測試,並且列出訂單。如果您需要同一個集合中的這兩個功能,請使用collections.OrderedDict

+0

無對象花費16個字節。如果只有一個默認的OrderedSet()。 :( – Sean 2017-11-06 08:43:48

13

回答你的第一個問題,set是一個針對集合操作進行優化的數據結構,並且像數學集合一樣,它不強制/維護元素的任何特定順序。集合的抽象概念不強制執行順序,所以不執行。當你從一個列表創建一個集合時,python會自由地改變元素的順序,以滿足它爲一個集合所使用的內部實現的需要,這個集合能夠高效地執行集合操作。

3

在其他的答案表示,集數據結構(和數學概念)不保留元素順序 -

然而,通過使用組和字典的結合,這是可能的,你可以實現wathever你想要的 - 嘗試使用這些內容摘要:在埃裏克森的回答

# 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 
1

大廈,我發現使用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() 
[1, 2, 20, 6, 210] 
+0

您需要執行'list(z.keys())'獲取列表輸出。 – jxn 2017-12-15 23:09:10

+0

in Python 3,yes。不在Python 2中,但我應該指定。 – jimh 2017-12-16 00:00:06

-5

這裏有一個簡單的方法來做到這一點:

x=[1,2,20,6,210] 
print sorted(set(x)) 
+2

這不會保留必要的順序 – 2016-11-15 16:47:18

+1

只有在輸入排序後,這個答案纔是正確的 – msudder 2016-12-20 17:27:50

10

在Python 3.6,set()現在應該維持秩序,但還有另一種Python 2和3的解決方案:

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

關於訂單保存的兩個注意事項:只有Python 3.6版本,甚至在那裏,它被認爲是一個實現細節,所以不要依賴它。除此之外,你的代碼是非常效率低下,因爲每次調用x.index時,都會執行線性搜索,如果您的系統複雜度很高,那麼沒有理由首先使用set。 – 2016-12-29 11:56:03

+9

@ThijsvanDien這是錯誤的,'' set()'在Python 3.6中沒有排序,甚至沒有作爲實現細節,你正在考慮'dict' – 2017-08-09 12:06:14

+0

@Chris_Rands我站得更正了;它們似乎被排序,而不是保持插入o刻申。無論哪種方式:實現細節。 – 2017-08-09 17:47:02