反復可能な項目をサブリストに分割する2つの関数があります。私はこのタイプの仕事は何度もプログラムされていると信じています。私はそれらを使用して( 'result'、 'case'、123、4.56)と( 'dump'、..)のようなrepr
行からなるログファイルを解析します。複数の連続した発電機を生産することができますか?
リストではなくイテレータを生成するようにこれらを変更したいと思います。リストはかなり大きくなるかもしれませんが、私はそれを取るか、最初のいくつかの項目に基づいてスキップすることができます。また、iterバージョンが利用可能な場合は、それらをネストしたいと思いますが、これらのリストバージョンでは、部分を複製することによっていくらかのメモリを無駄にするでしょう。
しかし、反復可能なソースから複数のジェネレータを派生させるのは簡単ではないので、私は助けを求めます。可能であれば、私は新しいクラスの導入を避けたいと考えています。
また、この質問のより良いタイトルが分かっている場合は教えてください。
ありがとうございました!
def cleave_by_mark (stream, key_fn, end_with_mark=False):
'''[f f t][t][f f] (true) [f f][t][t f f](false)'''
buf = []
for item in stream:
if key_fn(item):
if end_with_mark: buf.append(item)
if buf: yield buf
buf = []
if end_with_mark: continue
buf.append(item)
if buf: yield buf
def cleave_by_change (stream, key_fn):
'''[1 1 1][2 2][3][2 2 2 2]'''
prev = None
buf = []
for item in stream:
iden = key_fn(item)
if prev is None: prev = iden
if prev != iden:
yield buf
buf = []
prev = iden
buf.append(item)
if buf: yield buf
編集:私自身の答えは皆の答えに
おかげで、私は私が尋ね書くことができます!もちろん、「cleave_for_change」機能については、itertools.groupby
も使用できます。
def cleave_by_mark (stream, key_fn, end_with_mark=False):
hand = []
def gen():
key = key_fn(hand[0])
yield hand.pop(0)
while 1:
if end_with_mark and key: break
hand.append(stream.next())
key = key_fn(hand[0])
if (not end_with_mark) and key: break
yield hand.pop(0)
while 1:
# allow StopIteration in the main loop
if not hand: hand.append(stream.next())
yield gen()
for cl in cleave_by_mark (iter((1,0,0,1,1,0)), lambda x:x):
print list(cl), # start with 1
# -> [1, 0, 0] [1] [1, 0]
for cl in cleave_by_mark (iter((0,1,0,0,1,1,0)), lambda x:x):
print list(cl),
# -> [0] [1, 0, 0] [1] [1, 0]
for cl in cleave_by_mark (iter((1,0,0,1,1,0)), lambda x:x, True):
print list(cl), # end with 1
# -> [1] [0, 0, 1] [1] [0]
for cl in cleave_by_mark (iter((0,1,0,0,1,1,0)), lambda x:x, True):
print list(cl),
# -> [0, 1] [0, 0, 1] [1] [0]
/
def cleave_by_change (stream, key_fn):
'''[1 1 1][2 2][3][2 2 2 2]'''
hand = []
def gen():
headkey = key_fn(hand[0])
yield hand.pop(0)
while 1:
hand.append(stream.next())
key = key_fn(hand[0])
if key != headkey: break
yield hand.pop(0)
while 1:
# allow StopIteration in the main loop
if not hand: hand.append(stream.next())
yield gen()
for cl in cleave_by_change (iter((1,1,1,2,2,2,3,2)), lambda x:x):
print list(cl),
# -> [1, 1, 1] [2, 2, 2] [3] [2]
注意:誰もがこれらを使用するために起こって場合アンドリューが指摘したように、排気あらゆるレベルでの発電機に確認してください。そうでなければ、外側のジェネレータ降伏ループは、次の「ブロック」が始まるのではなく、内側のジェネレータが残っている場所ですぐに再スタートするからです。
stream = itertools.product('abc','1234', 'ABCD')
for a in iters.cleave_by_change(stream, lambda x:x[0]):
for b in iters.cleave_by_change(a, lambda x:x[1]):
print b.next()
for sink in b: pass
for sink in a: pass
('a', '1', 'A')
('b', '1', 'A')
('c', '1', 'A')
何をしたいことは可能であろう機能にフィルタ引数を提供することで、それが返される前に、リストを拒否したり、構築することである場合。このフィルタがリストプレフィックスを拒否すると、関数は現在の出力リストを投げ捨て、次のグループが開始されるまで出力リストに追加をスキップします。 –