2009-08-01 42 views
5

比方说,我有发电机功能是这样的:Python函数可以使用生成器并将生成器返回到其生成的输出的子集?

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) 

实施例输出可能是: ( '一个',1),( '一个',2),( 'A',3),( (a',5),('a',6),('a',7),('a',8),('b',9),('c ',10),('c',11),('c',12),('c',13)

我想把它分成三组:A组,B组和组C.我想为每个组都配一台发电机。然后,我会将生成器和组信转换为子功能。子功能的一个示例:

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()或打印机(),并避免在存储器中存储整个组在一旦? (在现实生活中,这些群体是巨大的

+1

在现实生活中,可以多次行走大型发电机吗?或者数据是否以某种不可挽回的方式消耗?如果我正确理解你的例子,那么调用random()的状态不会被存储在任何有用的地方,所以你不能再次使用该生成器。 – Nelson 2009-08-01 00:43:55

回答

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只是因为您所指定的printer签名接管数量的迭代器,而在本质上,在它得到它的输入相同的项目groupby返回迭代器 - 在这里,带有一个字母后跟一个数字的2项元组 - 但这与您的问题标题并不完全相关。

该标题的答案是,是的,一个Python函数可以很好地完成你想要的工作 - itertools.groupby实际上就是这么做的。我建议您仔细研究itertools模块,这是一个非常有用的工具(并且可以提供出色的性能)。

0

这里有一个小问题。你需要使用printer()函数为每个组采用一个生成器,但实际上你可以使用相同的生成器生成所有组。你有两个选择,因为我看到它:

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)更改打印机(),以保持状态,并通知当组变化(保持原来的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