Python dict.get()与多维dict

时间:2013-04-14 19:34:21

标签: python dictionary

我有一个多维dict,我希望能够通过键:密钥对检索值,如果第一个键不存在则返回'NA'。所有子序列都具有相同的密钥。

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

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

现在我只是检查顶级密钥是否存在,然后将子值分配给变量(如果存在)或“NA”(如果不存在)。但是,我这样做了大约500k次,还从其他地方检索/生成关于每个顶级密钥的其他信息,我正试图加快这一点。

4 个答案:

答案 0 :(得分:24)

怎么样

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

如果并非所有的subdicts都有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}
            })

答案 1 :(得分:4)

这是一种简单而有效的方法,可以使用普通字典进行操作,嵌套任意数量的级别:

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,))

虽然这样做的方式不如前者那么有效。

答案 2 :(得分:2)

您可以使用一个字典而不是嵌套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'

答案 3 :(得分:0)

获取多维dict示例的另一种方法(使用get方法两次)

{{1}}