3

yield次のようなジェネレーター関数を記述できるように、可変数のアイテムを作成できるようにしたいと思います。

x = [1, 2, 3]
y = [4, 5, 6]
z = [7, 8, 9]

def multi_enumerate(*iterables):
    n = 0
    iterators = map(iter, iterables)
    while iterators:
        yield n, *tuple(map(next, iterators))  # invalid syntax
        n += 1

for i,a,b,c in multi_enumerate(x, y, z):
    print i,a,b,c

誰かがこれを行うための何らかの方法を知っていますか?タプルを生成できることはわかっていますが、そのためには、次のように受信側でタプルを明示的に解凍する必要がありますa,b,c = t[0], t[1], t[2]

最終的な解決策

FWIW、John Kugelmanの優れた回答に基づいて、私が最終的に使用したものは次のとおりです。

from itertools import izip

def multi_enumerate(*iterables, **kwds):
    start = kwds.get('start')
    if start is None:
        if kwds: raise TypeError(
            "multi_enumerate() accepts only the keyword argument 'start'")
        try:
            iter(iterables[-1])  # last non-keyword arg something iterable?
        except TypeError:        # no, assume it's the start value
            start, iterables = iterables[-1], iterables[:-1]
        else:
            start = 0  # default

    return ((n,)+t for n, t in enumerate(izip(*iterables), start))

追加されたコードは、組み込み関数と同様に、0以外の開始値を指定する(またはstartキーワード引数を使用して指定する)オプションの反復不可能な最後の引数も受け入れるようにするためです。enumerate()

4

4 に答える 4

5

yieldステートメントを次のように変更します。

yield (n,) + tuple(map(next, iterators))

または、とを使用izipenumerateてループ全体を削除します。

from itertools import izip

def multi_enumerate(*iterables):
    return ((n,) + t for n, t in enumerate(izip(*iterables)))
于 2012-10-22T18:18:00.193 に答える
1

私はから使用chainitertoolsます:

yield tuple(chain((n,), map(next, iterators)))
于 2012-10-22T18:20:29.257 に答える
0

(n, *l[n])これにより、i n-lengthsを生成するイテレータが返されますl。メソッドの代わりに直接機能しますmultienumerate

from itertools import izip
def enumerated_columns(*rows):
    return izip(range(len(rows[0])), *rows)
于 2012-10-22T18:20:43.347 に答える
0

ジェネレーターから他のジェネレーターに複数のアイテムを委任する場合、これを行う1行の方法はありません—機能yield fromを備えたPython 3.3を使用しない限り、

ネストされたジェネレーターを繰り返し処理して、それらから値を明示的に生成します。

yield n
for value in (delegated.next for delegated in iterators):
  yield value
于 2012-10-22T18:22:47.353 に答える