簡體   English   中英

如何將 dict.get() 與多維 dict 一起使用?

[英]How to use dict.get() with multidimensional 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'如果不存在)。 但是,我這樣做了大約 50 萬次,並且還從其他地方檢索/生成有關每個頂級密鑰的其他信息,並且我正在嘗試加快速度。

怎么樣

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

這是一種簡單而有效的方法,可以使用嵌套任意數量的級別的普通字典來完成。 示例代碼適用於 Python 2 和 3。

from __future__ import print_function
try:
    from functools import reduce
except ImportError:  # Assume it's built-in (Python 2.x)
    pass

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)


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

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

它也可以遞歸完成:

# Recursive version.

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

雖然這種方法不如第一種有效。

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

另一種獲取多維字典示例的方法(使用兩次 get 方法)

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM