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

9 投票
3 回答
2060 浏览
提问于 2025-04-15 17:53

我有以下这段代码:

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

3 个回答

1

正如罗杰所预测的,这个回答并没有真正改善现有的代码 :)

a = ["one", "two", "three"]
for i in range(0, len(a)):
  print [val[1] for val in enumerate(a) if val[0] != i]
5
[items[:i]+items[i+1:] for i in range(len(items))]
>>> for a in itertools.combinations(items, len(items)-1):
    print(a)

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

在Python 2.x版本中,使用xrange。很明显,对于一个很大的序列,频繁切片并不是很高效,但对于短序列来说,这样做是可以的。更好的选择是使用itertools.combinations

17

虽然我的第一个解决方案得到了很多赞,但其实并不是提问者想要的结果。提问者想要的是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

可以查看这个链接了解下面讨论的来源。

撰写回答