迭代列表并在每次迭代中排除一个元素的更Pythonic方法

9

I have the following code:

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. "two", "three"
  2. "one", "three"
  3. "one", "two"
我现在编写的代码似乎有点像C++,有更好的解决方案吗?(我不想在一个变量中保存所有可能的列表)
编辑:我没有说明这一点,但列表的大小不一定为3。它可以是任何大小。
编辑2:似乎还有一个误解:如果我有一个N的列表,那么我希望得到N个大小为N-1的列表,每个列表都缺少原始列表中的一个元素。
编辑3:一个有4个项目的列表应该给出这个结果:
  1. 1, 2, 3
  2. 1, 3, 4
  3. 1, 2, 4
  4. 2, 3, 4

6
我预测你会收到十几个关于这个问题的答案,其中会涉及到 itertools 和生成器推导式,但最终可能还是没有比你最初的代码更好的提议。 - Jason Orendorff
不,他本可以使用xrange(len(items)) - Tobu
不,他已经在用Python 3了 :) - Tim Pietzcker
关于你的第二次编辑:不过,那并不是你原来的代码所给出的结果。 - balpha
1
我不知道为什么会有混淆,我认为我表达得很清楚了。无论如何,我添加了一个包含4个元素的列表示例。 - roger
显示剩余3条评论
3个回答

17
尽管被大量点赞,但我的第一个解决方案并不是 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

查看 修订历史记录 以了解以下讨论的来源。


1
但是我写的那个列表只是一个例子。在实践中,它可以是大小为N的。 - roger
5
实际上不是,我想要枚举长度为N-1的所有“组合”。 - roger
1
@罗杰:你还想要长度为2的所有组合吗? - balpha
确实如此。好吧,你得到了我的羞怯的+1。 - Jason Orendorff
1
请阅读我的编辑,我仍然认为你搞错了。combinations(L, len(L) - 1) 不应该是正确的方法吗? - roger
显示剩余4条评论

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

在Python 2.x中使用xrange。显然,在大序列上总是切片并不是很有效,但对于短序列来说这没问题。更好的选择是使用itertools.combinations

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

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

1
正如Roger所预测的那样,这个回答并没有真正改善现有的代码 :)
a = ["one", "two", "three"]
for i in range(0, len(a)):
  print [val[1] for val in enumerate(a) if val[0] != i]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接