2010-01-11 187 views
9

我有下面的代碼的更Python的方式:迭代一個清單,但一個元素每次迭代

items = ["one", "two", "three"] 

for i in range(0, len(items)): 
    for index, element in enumerate(items): 
     if index != i: 
      # do something with element 

基本上我想每個元素一次排除和迭代休息。所以對於名單上有以上情況,我想下面的迭代:

  1. 「二」,「三化」
  2. 「一」,「三化」
  3. 「一」,「二」

我寫的代碼現在看起來有點C++ - ish,有沒有更好的解決方案? (我不想在變量中保存所有可能的列表)

編輯:我沒有說明這一點,但列表大小不一定是3.它可以是任何大小。

編輯2:似乎還有另一個誤解:如果我有一個N的列表,那麼我想要N個大小爲N-1的列表,每個列表都缺少原始列表中的一個元素。

EDIT 3:具有4項列表,應該給該結果:

  1. 1,2,3
  2. 1,3,4
  3. 1,2,4
  4. 2, 3,4
+6

我預測你會得到一打的答案,這樣,'itertools答案'和發生器的理解將被調用,但最終沒有比你的初始代碼更好的建議。 – 2010-01-11 14:22:33

+0

那麼,他可以使用'xrange(len(items))'。 – Tobu 2010-01-11 14:27:23

+0

那麼,他已經在使用Python 3 :) – 2010-01-11 14:40:14

回答

17

雖然upvoted像瘋了一樣,但我的第一個解決方案並不是OP想要的,這是N個列表,每個都缺少N個原始元素中的一個:

>>> from itertools import combinations 
>>> L = ["one", "two", "three", "four"] 
>>> for R in combinations(L, len(L) - 1): 
...  print " and ".join(R) 
... 
one and two and three 
one and two and four 
one and three and four 
two and three and four 

查看revision history作爲以下討論的來源。

+1

但我寫的清單只是一個例子。實際上它可以是大小N. – roger 2010-01-11 14:34:02

+0

這比最初的代碼更加明確和清晰,所以我認爲它更合適?至少這是更pythonic。 – donut 2010-01-11 14:34:27

+5

居然不,我想迭代長度爲「N-1」的所有「組合」。 – roger 2010-01-11 14:39:01

5
[items[:i]+items[i+1:] for i in range(len(items))] 

在py2.x中使用xrange。顯然,在一個大序列上切片的時間不是非常有效,但對於短序列來說很好。更好的選擇是使用itertools.combinations

>>> for a in itertools.combinations(items, len(items)-1): 
    print(a) 

('one', 'two') 
('one', 'three') 
('two', 'three') 
1

羅傑預測,它並沒有真正改善現有的代碼:)

a = ["one", "two", "three"] 
for i in range(0, len(a)): 
    print [val[1] for val in enumerate(a) if val[0] != i]