2010-08-04 107 views
17

如果我有兩個相同的集合,意思是a == b給我True,它們是否具有相同的迭代順序?我試過了,它的工作原理:Python中集合的迭代順序

>>> foo = set("abc") 
>>> bar = set("abc") 
>>> zip(foo, bar) 
[('a', 'a'), ('c', 'c'), ('b', 'b')] 

我的問題是,我很幸運,還是這種行爲有保證?

+0

如果'一個是B'我認爲他們將具有相同的迭代順序。再次,這不是一個非常微妙的點= p – katrielalex 2010-08-04 14:27:02

回答

21

這不是只是巧合,他們出來是一樣的:實現恰好是確定性的,所以創建相同的集合兩次產生相同的排序。但是Python不能保證。

如果您在兩種不同的方式同一套:

n = set("abc") 
print n 

m = set("kabc") 
m.remove("k") 
print m 

...你可以得到不同的排序:

set(['a', 'c', 'b']) 
set(['a', 'b', 'c']) 
+0

+1最簡單的反例。 – katrielalex 2010-08-04 14:22:11

+0

另一個非常好的反例。謝謝! – 2010-08-04 14:25:00

+0

你是完全正確的:這不是巧合。例如,如果你直接創建相同的集合而不刪除任何東西,你總會得到相同的順序:例如:set(「abbacca」)給出set('a','c','b')如設置(「bbabbca」)。這種行爲是非隨機的並且與實現相關聯。看看python的源代碼會很有趣:) (但是在任何情況下,依靠它都是一個壞主意:)) – ThR37 2010-08-04 14:32:28

4

你很幸運,訂單不能保證。唯一可以保證的是這些套具有相同的元素。

如果您需要某種可預測性,您可以按如下所示對它們進行排序:zip(sorted(foo), sorted(bar))

0

我會說你很幸運。但是,也可能是因爲集合中的元素相同,所以它們按照相同的順序存儲。這種行爲不是你想要依賴的。

4

編號:

>>> class MyStr(str): 
...  def __hash__(self): 
...    return 0 
... 
>>> a = MyStr("a") 
>>> b = MyStr("b") 
>>> c = MyStr("c") 
>>> foo = { a, b, c } 
>>> foo 
{'c', 'b', 'a'} 
>>> bar = { b, a, c } 
>>> foo is bar 
False 
>>> foo == bar 
True 
>>> list(zip(foo, bar)) 
[('c', 'c'), ('b', 'a'), ('a', 'b')] 

附:我不知道__hash__覆蓋是否必要。我只是嘗試了一些我認爲會打破這一點的東西,而且確實如此。

+0

那麼,它證明了點。如果發生散列衝突,順序可能取決於我無法控制的事情。謝謝! – 2010-08-04 14:23:30

1

是的,你是幸運的。例如見:

import random 
r = [random.randint(1,10000) for i in range(20)] 
foo = set(r) 
r.sort(key=lambda _: random.randint(1,10000)) 
bar = set(r) 
print foo==bar 
print zip(foo, bar) 

這給我的結果:

True 
[(3234, 3234), (9393, 9393), (9361, 1097), (1097, 5994), (5994, 2044), (1614, 1614), (6074, 4377), (4377, 9361), (5202, 5202), (2355, 2355), (1012, 1012), (7349, 7349), (6198, 6198), (8489, 8489), (7929, 7929), (6556, 6074), (6971, 6971), (2044, 6556), (7133, 7133), (383, 383)]