You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用嵌套生成器与yield from保留嵌套结构实现元素过滤?

用嵌套生成器保留结构过滤嵌套列表元素

你现在需要处理嵌套列表a = [[1, 2], [3, 4, 5, 6], [7, 7, 8]],要过滤每个子容器里的偶数,同时保留原有的嵌套结构,目标输出是[[2], [4, 6], [8]]。之前用列表推导的nested_filter能实现,但想换成两个生成器函数避免创建中间列表,不过用yield from的写法会把结构扁平化,那该怎么调整呢?

先回顾你现有的代码:

现有列表版实现(可保留结构)

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

a = [[1, 2], [3, 4, 5, 6], [7, 7, 8]]
print(nested_filter(a))  # 输出: [[2], [4, 6], [8]]

问题:扁平化的生成器实现(非期望)

不管是直接嵌套循环的生成器,还是用yield from调用子生成器的写法,都会把结果扁平化:

# 直接嵌套循环的扁平化生成器
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]

# 用yield from的错误实现
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]

正确的嵌套生成器实现

要保留嵌套结构,关键是让外层生成器每次生成一个子生成器的迭代结果容器,而不是直接把内层元素平铺出来。这里提供两种实现方式:

方案1:拆分两个生成器函数

让内层生成器负责过滤子列表的偶数,外层生成器负责保留子结构,每次返回一个内层生成器实例:

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

def gen_outer(obj):
    for sub_obj in obj:
        # 每次yield一个内层生成器,保留子列表层级
        yield gen_inner(sub_obj)

a = [[1, 2], [3, 4, 5, 6], [7, 7, 8]]
# 转换为嵌套列表需要两层list转换
result = [list(sub_gen) for sub_gen in gen_outer(a)]
print(result)  # 输出: [[2], [4, 6], [8]]

方案2:用生成器表达式简化内层逻辑

如果不想单独写gen_inner,可以把内层过滤逻辑写成生成器表达式,直接在外层生成器中返回:

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

# 同样通过两层转换得到嵌套列表
result = [list(sub_gen) for sub_gen in nested_generator(a)]
print(result)  # 输出: [[2], [4, 6], [8]]

为什么之前的yield from不行?

yield from gen2(sub_obj)会把gen2产生的每个元素直接 yield 到外层,相当于把内层生成器的元素“平铺”到外层输出里,自然就丢失了嵌套结构。而我们需要的是外层生成器每次输出一个“子迭代器”,而非子迭代器里的单个元素,这样就能保留原有的层级。

额外验证

如果直接迭代gen_outer(a),你会得到三个生成器对象:

for sub_gen in gen_outer(a):
    print(sub_gen)
# 输出示例:
# <generator object gen_inner at 0x1023a5eb0>
# <generator object gen_inner at 0x1023a5f40>
# <generator object gen_inner at 0x1023a5fd0>

把每个子生成器转换成列表,就得到了我们想要的嵌套结构。

内容的提问来源于stack exchange,提问作者Brad Solomon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:43:53