5

次のようなジェネレーター関数があるとします。

import random
def big_gen():
  i = 0
  group = 'a'
  while group != 'd':
    i += 1
    yield (group, i)
    if random.random() < 0.20:
      group = chr(ord(group) + 1)

出力例: ('a', 1), ('a', 2), ('a', 3), ('a', 4), ('a', 5), ('a', 6)、('a'、7)、('a'、8)、('b'、9)、('c'、10)、('c'、11)、('c'、12) , ('c', 13)

これをグループ A、グループ B、グループ C の 3 つのグループに分けたいと思います。そして、グループごとにジェネレーターが必要です。次に、ジェネレータとグループ文字をサブ関数に渡します。サブ機能の例:

def printer(group_letter, generator):
  print "These numbers are in group %s:" % group_letter
  for num in generator:
    print "\t%s" % num

望ましい出力は次のようになります。

These numbers are in group a:
1
2
3
4
5
6
7
8
These numbers are in group b:
9
These numbers are in group c:
10
11
12
13

big_gen() または printer() を変更せずにこれを行うにはどうすればよいですか? また、グループ全体を一度にメモリに格納しないようにするにはどうすればよいですか? (実生活では、グループは巨大です)

4

2 に答える 2

8

確かに、これはあなたが望むことをします:

import itertools
import operator

def main():
  for let, gen in itertools.groupby(big_gen(), key=operator.itemgetter(0)):
    secgen = itertools.imap(operator.itemgetter(1), gen)
    printer(let, secgen)

groupbyは、ここでの作業の大部分を行いますkey=。グループ化するフィールドを指定するだけです。

結果のジェネレーターは、署名で数値の反復子を取るようにimap指定したという理由だけで、でラップする必要がありますが、本質的に、入力として取得したのと同じアイテムの反復子を返します。文字の後に数字が続きます-しかし、これは実際には質問のタイトルと密接な関係があるわけではありません.printergroupby

そのタイトルへの答えは、そうです、Python 関数はあなたが望む仕事を完全にうまく行うことができるということです -itertools.groupby実際、まさにそれを行います。itertoolsモジュールを注意深く調べることをお勧めします。これは非常に便利なツールです (そして素晴らしいパフォーマンスも提供します)。

于 2009-08-01T01:39:01.817 に答える
0

ここで少し問題があります。各グループのジェネレータを取得するために printer() 関数が必要ですが、実際にはすべてのグループを生成する同じジェネレータがあります。私が見ているように、あなたには2つのオプションがあります:

1) big_gen() を生成ジェネレーターを生成するように変更します。

import random
def big_gen():
  i = 0
  group = 'a'
  while group != 'd':
    def gen():
        i += 1
        yield i
        if random.random() < 0.20:
            group = chr(ord(group) + 1)
    yield group, gen

 from itertools import imap
 imap(lambda a: printer(*a), big_gen())

2) printer() を変更して状態を保持し、グループが変更されたときに通知します (元の big_gen() 関数を保持します):

def printer(generator):
  group = None
  for grp, num in generator:
    if grp != group:
        print "These numbers are in group %s:" % grp
        group = grp
    print "\t%s" % num
于 2009-08-01T00:40:26.543 に答える