Py学习  »  Python

Python递归字典搜索

Kikugie • 3 年前 • 1363 次点击  

我试图创建一个函数,该函数将嵌套数组(dict/list以任何顺序)和一个键名作为参数,并在列表中返回该键的所有值。

my_key = "Items"

my_dict = [{'z': 0, 'x': 0, 'y': 0, 'Items': [{'Slot': 1, 'id': 'minecraft:rail', 'Count': 1}, {'Slot': 2, 'id': 'minecraft:white_shulker_box', 'tag': {'BlockEntityTag': {'id': 'minecraft:shulker_box', 'Items': [{'Slot': 0, 'Count': 1, 'tag': {'Items': [{'id': 'minecraft:amethyst_shard', 'Count': 1}]}, 'id': 'minecraft:bundle'}]}}, 'Count': 1}]}]

def recursive_lookup(data, key):
    if isinstance(data, list):
        for i in data:
            recursive_lookup(i, key)
    elif isinstance(data, dict):
        for i, v in data.items():
            if i == key:
                print(f'{v = }')
            if isinstance(v, list) or isinstance(v, dict): recursive_lookup(v, key)
print(recursive_lookup(my_dict, my_key))

目前,它会在 print(f'{v = }') .如何将其存储在列表中并作为函数返回传递?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/128830
 
1363 次点击  
文章 [ 3 ]  |  最新文章 3 年前
2pichar
Reply   •   1 楼
2pichar    3 年前

您可以保留一份跑步列表:

def recursive_lookup(data, key):
    lst = []
    if isinstance(data, list):
        for i in data:
            lst.append(recursive_lookup(i, key))
    elif isinstance(data, dict):
        for i, v in data.items():
            if i == key:
                lst.append([v])
            if isinstance(v, list) or isinstance(v, dict): lst.append(recursive_lookup(v, key))
    return lst

print(recursive_lookup(data, 'Items'))
martineau Nae
Reply   •   2 楼
martineau Nae    3 年前

你可以随心所欲 没有 通过使用 json 标准库中的模块(假设您的数据可以序列化为该格式)。这是因为JSON解码器支持 object_hook 参数,它将在每次遇到字典时调用该函数。

其基本思想是通过这个参数指定一个函数,该函数只“监视”正在解码的内容,并检查它是否有所需的密钥。

我的意思是:

import json

my_key = "Items"
my_dict = [{'z': 0, 'x': 0, 'y': 0, 'Items': [{'Slot': 1, 'id': 'minecraft:rail', 'Count': 1}, {'Slot': 2, 'id': 'minecraft:white_shulker_box', 'tag': {'BlockEntityTag': {'id': 'minecraft:shulker_box', 'Items': [{'Slot': 0, 'Count': 1, 'tag': {'Items': [{'id': 'minecraft:amethyst_shard', 'Count': 1}]}, 'id': 'minecraft:bundle'}]}}, 'Count': 1}]}]

def lookup(data, key):
    results = []

    def decode_dict(a_dict):
        try:
            results.append(a_dict[key])
        except KeyError:
            pass
        return a_dict

    json_repr = json.dumps(data)  # Convert to JSON format.
    json.loads(json_repr, object_hook=decode_dict)  # Return value ignored.
    return results

from pprint import pprint
pprint(lookup(my_dict, my_key), sort_dicts=False)

打印精美的结果列表:

[[{'id': 'minecraft:amethyst_shard', 'Count': 1}],
 [{'Slot': 0,
   'Count': 1,
   'tag': {'Items': [{'id': 'minecraft:amethyst_shard', 'Count': 1}]},
   'id': 'minecraft:bundle'}],
 [{'Slot': 1, 'id': 'minecraft:rail', 'Count': 1},
  {'Slot': 2,
   'id': 'minecraft:white_shulker_box',
   'tag': {'BlockEntityTag': {'id': 'minecraft:shulker_box',
                              'Items': [{'Slot': 0,
                                         'Count': 1,
                                         'tag': {'Items': [{'id': 'minecraft:amethyst_shard',
                                                            'Count': 1}]},
                                         'id': 'minecraft:bundle'}]}},
   'Count': 1}]]

BrokenBenchmark
Reply   •   3 楼
BrokenBenchmark    3 年前

你可以用 .extend() 将递归调用的结果连接到列表。

def recursive_lookup(data, key):
    values = []
    if isinstance(data, list):
        for i in data:
            values.extend(recursive_lookup(i, key))
    elif isinstance(data, dict):
        for i, v in data.items():
            if i == key:
                values.append(v)
            if isinstance(v, list) or isinstance(v, dict):
                values.extend(recursive_lookup(v, key))
    return values