Python dict.get()与多维di

2024-05-31 23:16:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个多维dict,我希望能够通过key:key对检索值,如果第一个key不存在,则返回“NA”。所有的副词都有相同的键。

d = {   'a': {'j':1,'k':2},
        'b': {'j':2,'k':3},
        'd': {'j':1,'k':3}
    }

我知道我可以使用d.get('c','NA')来获取子dict(如果它存在的话)并返回'NA',否则我只需要子dict中的一个值。如果它存在的话,我想做类似d.get('c['j']','NA')的事情。

现在我只是检查顶级键是否存在,然后将子值赋给一个变量(如果存在)或“NA”(如果不存在)。不过,我已经做了大约500次了,而且还从其他地方检索/生成了关于每个顶级密钥的其他信息,我正在尝试加快速度。


Tags: key信息get地方密钥事情顶级dict
3条回答

与嵌套dict对象的层次结构不同,您可以使用一个字典,该字典的键是表示层次结构中路径的元组。

In [34]: d2 = {(x,y):d[x][y] for x in d for y in d[x]}

In [35]: d2
Out[35]:
{('a', 'j'): 1,
 ('a', 'k'): 2,
 ('b', 'j'): 2,
 ('b', 'k'): 3,
 ('d', 'j'): 1,
 ('d', 'k'): 3}

In [36]: timeit [d[x][y] for x,y in d2.keys()]
100000 loops, best of 3: 2.37 us per loop

In [37]: timeit [d2[x] for x in d2.keys()]
100000 loops, best of 3: 2.03 us per loop

以这种方式访问看起来要快15%。您仍然可以使用具有默认值的get方法:

In [38]: d2.get(('c','j'),'NA')
Out[38]: 'NA'

下面是一个简单而有效的方法来处理普通字典,嵌套任意数量的级别:

d = {'a': {'j': 1, 'k': 2},
     'b': {'j': 2, 'k': 3},
     'd': {'j': 1, 'k': 3},
    }

def chained_get(dct, *keys):
    SENTRY = object()
    def getter(level, key):
        return 'NA' if level is SENTRY else level.get(key, SENTRY)
    return reduce(getter, keys, dct)

print chained_get(d, 'a', 'j') # 1
print chained_get(d, 'b', 'k') # 3
print chained_get(d, 'k', 'j') # NA

它也可以递归地完成:

def chained_get(dct, *keys):
    SENTRY = object()
    def getter(level, keys):
        return (level if keys[0] is SENTRY else
                    'NA' if level is SENTRY else
                        getter(level.get(keys[0], SENTRY), keys[1:]))
    return getter(dct, keys+(SENTRY,))

尽管这样做的效率不如前者。

怎么样

d.get('a', {'j': 'NA'})['j']

是吗?

如果不是所有的子块都有一个j键,那么

d.get('a', {}).get('j', 'NA')

为了减少创建的相同对象,可以设计如下

class DefaultNASubdict(dict):
    class NADict(object):
        def __getitem__(self, k):
            return 'NA'

    NA = NADict()

    def __missing__(self, k):
        return self.NA

nadict = DefaultNASubdict({
                'a': {'j':1,'k':2},
                'b': {'j':2,'k':3},
                'd': {'j':1,'k':3}
            })

print nadict['a']['j']  # 1
print nadict['b']['j']  # 2
print nadict['c']['j']  # NA

使用defaultdict的相同想法:

import collections

class NADict(object):
    def __getitem__(self, k):
        return 'NA'

    @staticmethod
    def instance():
        return NADict._instance

NADict._instance = NADict()


nadict = collections.defaultdict(NADict.instance, {
                'a': {'j':1,'k':2},
                'b': {'j':2,'k':3},
                'd': {'j':1,'k':3}
            })

相关问题 更多 >