提取在嵌套字典和列表中找到的一组叶值,不包括无 [英] Extract set of leaf values found in nested dicts and lists excluding None

查看:21
本文介绍了提取在嵌套字典和列表中找到的一组叶值,不包括无的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个从 YAML 读取的嵌套结构,它由嵌套列表和/或嵌套字典组成,或者在不同嵌套级别上混合使用.可以假设该结构不包含任何递归对象.

I have a nested structure read from YAML which is composed of nested lists and/or nested dicts or a mix of both at various levels of nesting. It can be assumed that the structure doesn't contain any recursive objects.

如何仅从中提取叶值?另外,我不想要任何 None 值.叶值包含我只关心的字符串.使用递归是可以的,考虑到结构的最大深度不足以超过堆栈递归限制.生成器也可以选择.

How do I extract from it the leaf values only? Also, I don't want any None value. The leaf values contain strings which is all I care for. It's okay for recursion to be used, considering that the maximum depth of the structure is not large enough to exceed stack recursion limits. A generator would optionally also be fine.

存在处理扁平列表或字典的类似问题,但不是两者的混合.或者,如果扁平化一个 dict,它们也会返回扁平化的我并不真正需要的键,并冒着名称冲突的风险.

There exist similar questions which deal with flattening lists or dicts, but not a mix of both. Alternatively, if flattening a dict, they also return the flattened keys which I don't really need, and risk name conflicts.

我尝试了 more_itertools.collapse 但它的例子只显示它适用于嵌套列表,而不是字典和列表的混合.

I tried more_itertools.collapse but its examples only show it to work with nested lists, and not with a mix of dicts and lists.

struct1 = {
    "k0": None,
    "k1": "v1",
    "k2": ["v0", None, "v1"],
    "k3": ["v0", ["v1", "v2", None, ["v3"], ["v4", "v5"], []]],
    "k4": {"k0": None},
    "k5": {"k1": {"k2": {"k3": "v3", "k4": "v6"}, "k4": {}}},
    "k6": [{}, {"k1": "v7"}, {"k2": "v8", "k3": "v9", "k4": {"k5": {"k6": "v10"}, "k7": {}}}],
    "k7": {
        "k0": [],
        "k1": ["v11"],
        "k2": ["v12", "v13"],
        "k3": ["v14", ["v15"]],
        "k4": [["v16"], ["v17"]],
        "k5": ["v18", ["v19", "v20", ["v21", "v22", []]]],
    },
}

struct2 = ["aa", "bb", "cc", ["dd", "ee", ["ff", "gg"], None, []]]

预期产出

struct1_leaves = {f"v{i}" for i in range(23)}
struct2_leaves = {f"{s}{s}" for s in "abcdefg"}

推荐答案

这是对 参考答案 的改编以供使用一个内部函数和一个 set.它还使用递归来为问题中包含的样本输入生成预期输出.它避免通过整个调用堆栈传递每个叶子.

This is an adaption of the reference answer to use an inner function and a single set. It also uses recursion to produce the expected outputs for the sample inputs included in the question. It avoids passing every leaf through the entire call stack.

from typing import Any, Set


def leaves(struct: Any) -> Set[Any]:
    """Return a set of leaf values found in nested dicts and lists excluding None values."""
    # Ref: https://stackoverflow.com/a/59832594/
    values = set()

    def add_leaves(struct_: Any) -> None:
        if isinstance(struct_, dict):
            for sub_struct in struct_.values():
                add_leaves(sub_struct)
        elif isinstance(struct_, list):
            for sub_struct in struct_:
                add_leaves(sub_struct)
        elif struct_ is not None:
            values.add(struct_)

    add_leaves(struct)
    return values

这篇关于提取在嵌套字典和列表中找到的一组叶值,不包括无的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆