扁平优于嵌套:如何处理深度嵌套的字典?

Rap*_*ael 4 python python-3.x

在我作为工程师(不是软件)的工作中,有时我必须用 Python 编程。按照教程,我了解了字典以及它们如何用于存储数据,它们的速度很快等等。

我嵌套的字典可以达到 7 级,如下所示:

mydict['level1']['level2']['level3']['level4']['level5']['level6']['level7']
Run Code Online (Sandbox Code Playgroud)

我有这些小怪物,因为我解析了一个带有库的文档,该库返回如下内容:

mydict['level1']['level2']['level3']['level4']['level5']['level6']['level7']
Run Code Online (Sandbox Code Playgroud)

我还有其他深度嵌套的字典。

我面临的问题是我需要迭代到最后一级来获取和过滤结果,因为我事先不知道键,所以我像下面的伪代码一样迭代:

例一:漂亮的

components['comp1']['comp_name']
components['comp1']['comp_dimension']
components['comp1']['subcomponents']['subcomp1']
components['comp1']['subcomponents']['subcomp1']['comp_name1']
etc.
Run Code Online (Sandbox Code Playgroud)

示例 2:有点丑(下降了 3 个级别,还有 4 个级别……):

filter_subcomps = ["comp1", "comp10"]
filter_value = 10.0

for component in components
    comp_name = components[component]['comp_name']
    comp_dimension = components[component]['comp_dimension']
    if components[component].get('subcomponents', False):
        subcomp_keys = filter_subcomps if filter_subcomps else components[component]['subcomponents'].keys()
        for subcomponent in subcomp_keys:
            etc etc
            if value > X:
                return value
Run Code Online (Sandbox Code Playgroud)

这些是一个相当简单的例子,有时代码会出现超过 10 级的缩进,这看起来很糟糕,我不得不水平滚动页面。除此之外,即使是我在几天或几周后阅读代码也很困难。

我从人们那里阅读了一些教程,这些教程将表格数据转换为嵌套的字典,反之亦然,甚至有人使用 xpath 访问字典键。

无论如何,遵循python的禅宗我当然不尊重“扁平比嵌套更好”,因为我的代码进入了天文级别的缩进。

我正在考虑将所有嵌套的 dict 转换为 SQLite 并使用 SQL 语言进行查询,而不是使用这些丑陋的 for 循环和 if 条件。所以我该怎么做?我如何处理 Python 中的嵌套字典,同时尽可能保持代码扁平化?我有点迷失在这里。

PS:我的问题与“扁平优于嵌套”无关- 对于数据和代码?因为我已经有了深度嵌套的字典。我想知道如何处理这些 dicts、查询/过滤值等,同时有一个平面代码。

Max*_*Noe 5

我不会改变数据结构。如果这就是你得到的并且它很好地模拟了问题,那就这样吧。

将您的代码拆分为一些小的函数,这些函数在结构的更深层次。


def filter_components(components, keys, value):
    # if key is not needed, use .values()
    for key, component in components.items():
        if 'subcomponents' in component:
            filter_subcomponent(component['subcomponents'], keys, value)


def filter_subcomponents(subcomps, keys, values):
    for subcomp in subcombs.values():
        # do stuff 
Run Code Online (Sandbox Code Playgroud)

如果更复杂,则拆分更多。完成部分工作的小而易读的函数。

  • 在某个地方,这些循环将会存在。根据具体情况,您也许可以使用递归编写简洁的代码。但这只会将环路隐藏起来 (2认同)

Eug*_*its 1

有几种解决该问题的方法:

  1. 使结构扁平化。如果您认为平面表的处理会更快,那么将您的结构展平为类或结构实例的简单列表,然后处理该简单列表可能是有意义的。
  2. 如果各个级别的结构是统一的(即使每个级别的名称不同),则可以使用简单递归。您将拥有一个函数,该函数将检查某个级别上的项目是否有子项,并在每个子项存在时调用自身,或者调用最终级别条目的数据处理函数。如果子组件名称不同,您可以拥有一个此类名称的数组,其中表示“在级别 1 上,这些项目称为“comp*”,在级别 2 上称为“subcomp*”,依此类推。
  3. 如果级别需要完全不同的处理,请为每个级别引入单独的函数。