2010-01-11 145 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] 
相关问题