我有一个多维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次,还从其他地方检索/生成关于每个顶级密钥的其他信息,我正试图加快这一点。
答案 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}}