7

假设我有一个任意嵌套的字典:

d = {
    11: {
        21: {31: 'a', 32: 'b'},
        22: {31: 'a', 34: 'c'},
    },
    12: {
        1: {2: 3}
    }
}

还有一个键列表,其位置告诉我要在哪个嵌套字典中查找每个键:

keys = [11, 21, 31]
# keys = [11, 23, 44]

是否有一个简单的班轮来做到这一点?我查看了下面列出的问题,它们很相似,但并不是我真正想要的。我自己也尝试过并想出了这个:

from functools import reduce

def lookup(d, key):
    return d.get(key, {}) if d and isinstance(d, dict) else None

def fn(keys, d):
    return reduce(lookup, keys, d)

print(fn(keys, d)) # prints 'a'

这样做的问题是,在第二个键列表的情况下(请参阅注释掉的键),它会继续进一步查找嵌套键,即使没有找到更高级别的键,并且继续是没有意义的。reduce一旦我找到最终匹配或失败,我该如何停止(下面列出的问题之一解决了它,但我不能真正将它应用到我的用例中......或者我可以吗?)?还有其他想法吗?哦,我只想使用官方 python 库来完成这个。所以 nonumpypandas,但是functoolsitertools都很好

Python:将列表转换为具有异常处理的多维字典的字典键

是否有一个简单的单行代码来访问 Python 中嵌套字典的每个元素?

在 Python 3.3 中访问嵌套字典中的嵌套值

使用 itertools 进行递归函数应用

中途停止 Reduce() 操作。进行部分运行总和的功能方式

在字典中递归查找键

谢谢!

4

3 回答 3

10

您可以使用functools.reduce()

from functools import reduce # In Python 2, don't import it. (It's a built-in)

print(reduce(dict.get, keys, d))

# 'a'

对于您提到的键,它是这样的:

  • dict.get用(initial) 和( d) 的第一项调用以获得keys11d[11]
  • dict.get使用结果(字典)和keys( ) 中的下一项调用21以获取{...}[21]
  • 打电话dict.get……
    _

直到keys被“减少”到最终值 ( 'a')

编辑:如果没有这样的键,结果可能是不希望的结果dict.getNone如果你想拥有一个KeyError,你可以使用operator.getitem

于 2016-04-12T21:37:56.917 回答
0

这是我想出的一个解决方案,当给定无效的查找路径时,它还会返回有用的信息,并允许您挖掘任意 json,包括嵌套列表和 dict 结构。(对不起,它不是单线)。

def get_furthest(s, path):
    '''
    Gets the furthest value along a given key path in a subscriptable structure.

    subscriptable, list -> any
    :param s: the subscriptable structure to examine
    :param path: the lookup path to follow
    :return: a tuple of the value at the furthest valid key, and whether the full path is valid
    '''

    def step_key(acc, key):
        s = acc[0]
        if isinstance(s, str):
            return (s, False)
        try:
            return (s[key], acc[1])
        except LookupError:
            return (s, False)

    return reduce(step_key, path, (s, True))
于 2018-03-06T21:13:03.617 回答
-2
d = {
    11: {
        21: {
            31: 'a from dict'
        },
    },
}

l = [None] * 50
l[11] = [None] * 50
l[11][21] = [None] * 50
l[11][21][31] = 'a from list'

from functools import reduce

goodkeys = [11, 21, 31]
badkeys = [11, 12, 13]

print("Reducing dictionary (good):", reduce(lambda c,k: c.__getitem__(k), goodkeys, d))
try:
    print("Reducing dictionary (bad):", reduce(lambda c,k: c.__getitem__(k), badkeys, d))
except Exception as ex:
    print(type(ex), ex)

print("Reducing list (good):", reduce(lambda c,k: c.__getitem__(k), goodkeys, l))

try:
    print("Reducing list (bad):", reduce(lambda c,k: c.__getitem__(k), badkeys, l))
except Exception as ex:
    print(type(ex), ex)
于 2016-04-12T21:53:59.220 回答