2

2 つの要素を追加して展開する必要があるタプルのリストがあり、それぞれがリストから取得されます。したがって[(1, 2, 3)]、2 つのイテレータit1 = (i for i in ['a1', 'a2'])とがありit2 = (i for i in in ['b1', 'b2'])ます。結果は になります[(1, 2, 3, 'a1', 'b1'), (1, 2, 3, 'a1', 'b2'), (1, 2, 3, 'a2', 'b1'), (1, 2, 3, 'a2', 'b2')]

上記のようにイテレータを使用すると、機能しません。しかし、リストを使用すると機能します。コードは次のとおりです。

def get_iters():
    return ((i for i in ['a1', 'a2']), (i for i in ['b1', 'b2']))

def get_lists():
    return ([i for i in ['a1', 'a2']], [i for i in ['b1', 'b2']])

def compose(lst_of_tuples, iter=True):
    iters = get_iters() if iter else get_lists()
    for it in iters:
        lst_of_tuples = [t + (i,) for t in lst_of_tuples for i in it]
    return lst_of_tuples

print compose([(1,2,3)], True)
# WRONG!???? (what happened to the 'a2' part of it?)
# prints: [(1, 2, 3, 'a1', 'b1'), (1, 2, 3, 'a1', 'b2')]

print compose([(1,2,3)], False)
# RIGHT!! prints: [(1, 2, 3, 'a1', 'b1'), (1, 2, 3, 'a1', 'b2'), (1, 2, 3, 'a2', 'b1'), (1, 2, 3, 'a2', 'b2')]

そうなる理由が思いつきません。誰か説明できますか?

4

1 に答える 1

5

Iterables は1 回だけ反復でき、その後は使い果たされます。

for ループで特定の iterable を 2 回ループすると、それ以上の要素は返されません。

代わりに最初にループしitertools.product()、次にタプルのリストをループして出力を生成します。

from itertools import product

def compose(lst_of_tuples, iter=True):
    iters = get_iters() if iter else get_lists()
    return [t + i for i in product(*get_iters()) for t in lst_of_tuples]

これにより、次が生成されます。

>>> print compose([(1,2,3)], True)
[(1, 2, 3, 'a1', 'b1'), (1, 2, 3, 'a1', 'b2'), (1, 2, 3, 'a2', 'b1'), (1, 2, 3, 'a2', 'b2')]
>>> print compose([(1,2,3)], False)
[(1, 2, 3, 'a1', 'b1'), (1, 2, 3, 'a1', 'b2'), (1, 2, 3, 'a2', 'b1'), (1, 2, 3, 'a2', 'b2')]
于 2013-05-16T19:39:01.583 に答える