【问题标题】:How to loop through nested python dictionary with below structure?如何遍历具有以下结构的嵌套python字典?
【发布时间】:2020-09-19 10:14:05
【问题描述】:

我有以下结构的嵌套字典。像键 values 一样,可能有多个键,例如 values1values2。我正在寻找 random1random2 字符串。如果存在,则必须检查val是否存在。

d = {"values": [
        {
          "name": "A1234",
          "description": "A1234-Description ",
          "random1": {
            "abcd": {
              "val": 1
            }
          },
          "random2": {
            "abcd": {
              "val": -1
            }
          }
        },
        {
        "name": "A4567",
          "description": "A4567-Description ",
          "random1": {
            "abcd": {
              "val": 1
            }
          },
          "random2": {
            "abcd": {
              "val": -1
            }
          }
        },
        {
          "name": "B1234",
          "description": "B1234-Description ",
        }
    ]}

代码:

for i in d["values"]:
    for k, v in i.items():
        if k in ("random1", "random2") and "abcd" in v1:
           if len(v1["abcd"]) != 0:
              if "val" in v1["abcd"]:
                  print("Found")
              else:
                  print("Not found")
           else:
               print("empty")

我相信循环到字典没有捷径。但绝对应该有一些技术/优化来做到这一点(减少多个 for/if 循环)

任何人都可以请指导我,如果它可以通过使用集合等来完成

【问题讨论】:

  • 你想要的输出是什么? Found, Not Found, empty 对应每个 randonm[12] -> abcd?
  • @schwobaseggl : 对于每个 random1 或 random2,找到或未找到 'val'。

标签: python-3.x collections


【解决方案1】:

你需要一个递归算法来遍历字典的树状结构

def recursive_iter(obj, keys=()):
    if isinstance(obj, dict):
        for k, v in obj.items():
            yield from recursive_iter(v, keys + (k,))
    elif any(isinstance(obj, t) for t in (list, tuple)):
        for idx, item in enumerate(obj):
            yield from recursive_iter(item, keys + (idx,))
    else:
        yield keys, obj

在这里你可以打印结果

for keys, item in recursive_iter(d):
    print(keys, ' -> ', item)

哪些显示:

('values', 0, 'name')  ->  A1234
('values', 0, 'description')  ->  A1234-Description 
('values', 0, 'random1', 'abcd', 'val')  ->  1
('values', 0, 'random2', 'abcd', 'val')  ->  -1
('values', 1, 'name')  ->  A4567
('values', 1, 'description')  ->  A4567-Description 
('values', 1, 'random1', 'abcd', 'val')  ->  1
('values', 1, 'random2', 'abcd', 'val')  ->  -1
('values', 2, 'name')  ->  B1234
('values', 2, 'description')  ->  B1234-Description

编辑:

for keys, item in recursive_iter(d):
    if "val" in keys and "abcd" in keys:
        print("FOUND\n", keys, ' -> ', item)
    elif "val" not in keys and "abcd" in keys:
        print("NOT FOUND\n", keys, ' -> ', item)

【讨论】:

  • 我们必须确保“val”用于“random1”或“random2”或两者的“abcd”。
  • 为什么检查项目 == 1 和项目 == -1 ?
  • val = 1 还是 -1,只是为了检查 'random1' 或 'random2' 或两者的 "abcd" 是否存在 "val"
  • 如果按照字典顺序,如果除了 d["values"][index].keys() 中的 'random1' 和 'random2' 之外的任何内容,都不应该打扰。应该考虑,如果它只是'random1''random2'
  • 我编辑了。实际上,由于您的查询与递归探索无关,并且如果您的 Dictionary 始终采用这种格式,那么您的脚本已经很好了。您可以跳过第二个 for 循环并合并到您的 if 语句中:if 'random1' in i and 'abcd' in i['random1']: if 'random2' in i and 'abcd' in i['random2']: if 'random1' not in i and 'random2' not in i:
猜你喜欢
  • 2013-07-21
  • 2015-06-03
  • 1970-01-01
  • 2022-01-24
  • 2017-07-25
相关资源
最近更新 更多