简体   繁体   English

嵌套发电机和产量来自?

[英]Nested generators and yield from?

I have an nested object, a , and want to apply some type of filter on each of its sub-containers: 我有一个嵌套对象, a ,并希望在每个子容器上应用某种类型的过滤器:

a = [[1, 2], [3, 4, 5, 6], [7, 7, 8]]

A function to keep the nested structure but filter to only even elements would look like: 保持嵌套结构但仅过滤偶数元素的函数如下所示:

def nested_filter(obj):
    res = []
    for sub_obj in obj:
        even = [i for i in sub_obj if i % 2 == 0]
        res.append(even)
    return res

nested_filter(a)
# [[2], [4, 6], [8]]

But I would like to create an equivalent generator that uses some form a nested yield to maintain the nested structure of a . 不过,我想创建一个使用某种形式的嵌套同等发电机yield保持嵌套结构a

This, for illustration, is exactly what I do not want because it flattens a : 此,为了说明,正是我不想要的东西,因为它变平a

def nested_yield(obj):
    """Will flatten the nested structure of obj."""
    for sub_obj in obj:
        for i in sub_obj:
            if i % 2 == 0:
                yield i

list(nested_yield(a))
# [2, 4, 6, 8]

My understanding was that yield from , introduced in Python 3.3 , might allow for nesting that retains the structure of the passed object. 我的理解是, Python 3.3中引入的 yield from可能允许嵌套保留传递对象的结构。 But apparently I am misinterpreting: 但显然我误解了:

def gen1(obj):
    for sub_obj in obj:
        yield from gen2(sub_obj)


def gen2(sub_obj):
    for i in sub_obj:
        if i % 2 == 0:
            yield i

list(gen1(a))
# [2, 4, 6, 8]

So, is there any way I can use two generator functions (ie not create intermediate lists) so that calling the generator would give me this: 那么,有什么方法可以使用两个生成器函数(即不创建中间列表),以便调用生成器会给我这样的:

list(nested_generator(a))
# [[2], [4, 6], [8]]

You want your nested_generator to return a list of sublists. 您希望nested_generator返回一个子列表列表。 In this case, you cannot get around creating temporary lists at the inner level. 在这种情况下,您无法在内层创建临时列表。

So, your best option is to yield the filtered list: 因此,您最好的选择是产生过滤后的列表:

>>> def nested_filter(L):
    for l in L:
        yield [i for i in l if i % 2 == 0]


>>> a = [[1, 2], [3, 4, 5, 6], [7, 7, 8]]
>>> list(nested_filter(a))
[[2], [4, 6], [8]]

If you want to use a second generator to filter your sub-list, you can convert the iterator returned to a list and yield that as well: 如果你想使用第二个发电机来筛选子列表,你可以转换迭代器返回到列表中,并yield这还有:

>>> def generator_filter(L):
    for n in L:
        if n % 2 == 0:
            yield n


>>> def nested_filter(L):
    for l in L:
        yield list(generator_filter(l))


>>> a = [[1, 2], [3, 4, 5, 6], [7, 7, 8]]
>>> list(nested_generator(a))
[[2], [4, 6], [8]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM