0

我想按 3 项对列表进行分组,并尽可能简洁地按 2 项组合对每个这样的组进行迭代。我尝试了几件事,其中一个甚至没有编译:

from itertools import combinations
L = [1,2,3,4,5,6]
for a,b in combinations(zip(*[iter(L)]*3), 2): 
    print "{0:d} {1:d}".format(a,b)

预期产出

1,2
1,3
2,3
4,5
4,6
5,6

我可以通过命令式语句来做到这一点,但我正在寻找一种声明性的方式。

4

3 回答 3

2

您正在接近,但您需要将该combinations()函数应用于zip()grouper 序列输出中的每个元组:

from itertools import combinations, chain

for a, b in chain.from_iterable(combinations(group, 2) for group in zip(*[iter(a)]*3)):
    print "{} {}".format(a,b)

由于您现在有一个结果序列combinations()我曾经chain.from_iterable()将每个结果的输出合并到一个最终序列中。

这会产生所需的输出:

>>> for a, b in chain.from_iterable(combinations(group, 2) for group in zip(*[iter(a)]*3)):
...     print "{} {}".format(a,b)
... 
1 2
1 3
2 3
4 5
4 6
5 6
于 2013-04-16T13:32:55.537 回答
2

你很近。您需要一次进行组合 1 分组,然后再chain进行结果(实际上,chain.from_iterable这里更合适)。

from itertools import combinations,chain

lst = [1,2,3,4,5,6]
def group(a,n):
    return zip(*[iter(a)]*n)

for a,b in chain.from_iterable(combinations(grp, 2) for grp in group(lst,3)): 
    print "{0} {1}".format(a,b)
于 2013-04-16T13:32:14.223 回答
1

这是一个基于itertoolsandoperator的解决方案。不像其他解决方案那样简洁,但 FWIW:

from itertools import imap, combinations, repeat, count, takewhile, izip, chain
from operator import getitem, truth
L = [1,2,3,4,5,6]
slicers = izip(count(0, 3), count(3, 3))
slices = (getitem(L, slice(*x)) for x in slicers)
slices = takewhile(truth, slices)
for x in chain.from_iterable(imap(combinations, slices, repeat(2))):
    print x

...
(1, 2)
(1, 3)
(2, 3)
(4, 5)
(4, 6)
(5, 6)
于 2013-04-16T14:12:57.930 回答