简体   繁体   English

在python中迭代dict dict的dict

[英]Iterate dict of dict of dict in python

I have dict on dict of dict . 我对dict的词典有所了解。 And I want a function which will return all the details if arguement matches the key like, 我想要一个函数,如果争论与键匹配,将返回所有细节,如,

identifiers = {
     '42566431313931326462642d3533656132352033': {         
         'name': 'topleft',         
         'subid': {
            'a3e54b84450000': {
                'name': 'north'                
            }
        }        
    },
    '0942378098093': {         
         'name': 'topright',         
         'subid': {
            '4b840000100000000000': {
                'name': 'north'                
            }
        }        
    },
    '4256643131ra98892389': {         
         'name': 'bottomleft',         
         'subid': {
            'a3e54b840000100000000000': {
                'name': 'west'                
            }
        }        
    }
}

def getdetails(p):
    # p could be key of dict or dict of dict
    for key in identifiers:
        if key == p:
            return identifiers[key]        
        else:
            if p in identifiers[key]['subid']:
                return identifiers[key]['subid'][p]

I want to know if there is elegent way to do it (May be using map and lambda)? 我想知道是否有更好的方法(可能是使用map和lambda)?

Readability is important. 可读性很重要。 As your code is readable, I would improve the code slightly, like this 由于您的代码是可读的,我会略微改进代码,就像这样

def getdetails(p):
    if p in ids:
        return ids[p]

    for k, v in ids.iteritems():
        if p in v['subid']:
            return v['subid'][p]

But if you are looking for one-liners, you can create a generator expression and return the first value got from that. 但是如果你正在寻找单行,你可以创建一个生成器表达式并返回从中得到的第一个值。

def getdetails(p):
    if p in ids: return ids[p]
    return next(v['subid'][p] for k, v in ids.iteritems() if p in v['subid'])

You can further shorten the code, like this 您可以像这样进一步缩短代码

def getdetails(p):
    return ids.get(p) or next(v['subid'][p] for k, v in ids.iteritems() if p in v['subid'])

The dict.get will return None if the key is not found in the dictionary and that is considered Falsy in Python. 如果在字典中找不到密钥并且在Python中被认为是Falsy,则dict.get将返回None So, if it is not in the main dictionary, we will check in the sub dictionaries. 因此,如果它不在主词典中,我们将检查子词典。

If you are using Python 3.x, you need to use items method instead of iteritems , like this 如果您使用的是Python 3.x,则需要使用items方法而不是iteritems ,就像这样

def getdetails(p):
    return ids.get(p) or next(v['subid'][p] for k, v in ids.items() if p in v['subid'])
for key,value in identifiers.items():
        if key == p:
            return identifiers[key]        
        else:
            if p in identifiers[key]['subid']:
                return identifiers[key]['subid'][p]

If you are sure p to be inside subid if not in top level may be something like below would work as well. 如果你确定psubid如果不在顶层可能会像下面那样工作。

def getdetails(p):
    req_val = identifiers.get(p)
    if not req_val:
       for key, value in identifiers.items():
            req_val = value['subid'].get(p)
    return req_val

Try recursion like this: 尝试这样的递归:

def getdetails(p, dictionary):
    result = []
    if type(dictionary) is not dict:
        return result
    for key in dictionary:
        if key == p:
            result.append(dictionary[p])
        result += getdetails(p, dictionary[key])

    return result

print getdetails('name', identifiers)
print getdetails('subid', identifiers)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM