Python嵌套字典函数重构

时间:2014-06-13 18:19:41

标签: python recursion dictionary

我有一个字典,其中包含一堆键/值对,其中一些键是字符串,其他键是更多字典,依此类推。

这是我正在使用的示例词典:

{'1': {'0': {'hl': '', 'object_id': '590', 'state': 'T'},
       '1': {'hl': '', 'object_id': '590', 'state': 'T'},
       '2': {'hl': '', 'object_id': '590', 'state': 'T'}},
 '10': {'0': {'hl': '', 'object_id': '1194', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1194', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1194', 'state': 'T'}},
 '11': {'0': {'hl': '', 'object_id': '1195', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1195', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1195', 'state': 'T'}},
 '12': {'0': {'hl': '', 'object_id': '1196', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1196', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1196', 'state': 'T'}},
 '13': {'0': {'hl': '', 'object_id': '1197', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1197', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1197', 'state': 'T'}},
 '14': {'0': {'hl': '', 'object_id': '1198', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1198', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1198', 'state': 'T'}},
 '15': {'0': {'hl': '', 'object_id': '1199', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1199', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1199', 'state': 'T'}},
 '16': {'0': {'hl': '', 'object_id': '1200', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1200', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1200', 'state': 'T'}},
 '17': {'0': {'hl': '', 'object_id': '1201', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1201', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1201', 'state': 'T'}},
 '18': {'0': {'hl': '', 'object_id': '1202', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1202', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1202', 'state': 'T'}},
 '19': {'0': {'hl': '', 'object_id': '554', 'state': 'T'},
        '1': {'hl': '', 'object_id': '554', 'state': 'T'},
        '2': {'hl': '', 'object_id': '554', 'state': 'T'}},
 '2': {'0': {'hl': '', 'object_id': '590', 'state': 'T'},
       '1': {'hl': '', 'object_id': '590', 'state': 'T'},
       '2': {'hl': '', 'object_id': '590', 'state': 'T'}},
 '20': {'0': {'hl': '', 'object_id': '554', 'state': 'T'},
        '1': {'hl': '', 'object_id': '554', 'state': 'T'},
        '2': {'hl': '', 'object_id': '554', 'state': 'T'}},
 '21': {'0': {'hl': '', 'object_id': '949', 'state': 'T'},
        '1': {'hl': '', 'object_id': '949', 'state': 'T'},
        '2': {'hl': '', 'object_id': '949', 'state': 'T'}},
 '22': {'0': {'hl': '', 'object_id': '954', 'state': 'T'},
        '1': {'hl': '', 'object_id': '954', 'state': 'T'},
        '2': {'hl': '', 'object_id': '954', 'state': 'T'}},
 '23': {'0': {'hl': '', 'object_id': '554', 'state': 'T'},
        '1': {'hl': '', 'object_id': '554', 'state': 'T'},
        '2': {'hl': '', 'object_id': '554', 'state': 'T'}},
 '24': {'0': {'hl': '', 'object_id': '554', 'state': 'T'},
        '1': {'hl': '', 'object_id': '554', 'state': 'T'},
        '2': {'hl': '', 'object_id': '554', 'state': 'T'}},
 '25': {'0': {'hl': '', 'object_id': '1203', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1203', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1203', 'state': 'T'}},
 '26': {'0': {'hl': '', 'object_id': '1204', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1204', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1204', 'state': 'T'}},
 '27': {'0': {'hl': '', 'object_id': '1220', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1220', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1220', 'state': 'T'}},
 '28': {'0': {'hl': '', 'object_id': '1221', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1221', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1221', 'state': 'T'}},
 '29': {'0': {'hl': '', 'object_id': '1222', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1222', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1222', 'state': 'T'}},
 '3': {'0': {'hl': '', 'object_id': '590', 'state': 'T'},
       '1': {'hl': '', 'object_id': '590', 'state': 'T'},
       '2': {'hl': '', 'object_id': '590', 'state': 'T'}},
 '30': {'0': {'hl': '', 'object_id': '1223', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1223', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1223', 'state': 'T'}},
 '31': {'0': {'hl': '', 'object_id': '1224', 'state': 'T'},
        '1': {'hl': '', 'object_id': '1224', 'state': 'T'},
        '2': {'hl': '', 'object_id': '1224', 'state': 'T'}},
 '32': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '33': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '34': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '35': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '36': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '37': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '38': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '39': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '4': {'0': {'hl': '', 'object_id': '590', 'state': 'T'},
       '1': {'hl': '', 'object_id': '590', 'state': 'T'},
       '2': {'hl': '', 'object_id': '590', 'state': 'T'}},
 '40': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '41': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '42': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '43': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '44': {'0': {'state': 'F'}, '1': {'state': 'F'}, '2': {'state': 'F'}},
 '5': {'0': {'hl': '', 'object_id': '1010', 'state': 'T'},
       '1': {'hl': '', 'object_id': '1010', 'state': 'T'},
       '2': {'hl': '', 'object_id': '1010', 'state': 'T'}},
 '6': {'0': {'hl': '', 'object_id': '1010', 'state': 'T'},
       '1': {'hl': '', 'object_id': '1010', 'state': 'T'},
       '2': {'hl': '', 'object_id': '1010', 'state': 'T'}},
 '7': {'0': {'hl': '', 'object_id': '1010', 'state': 'T'},
       '1': {'hl': '', 'object_id': '1010', 'state': 'T'},
       '2': {'hl': '', 'object_id': '1010', 'state': 'T'}},
 '8': {'0': {'hl': '', 'object_id': '1010', 'state': 'T'},
       '1': {'hl': '', 'object_id': '1010', 'state': 'T'},
       '2': {'hl': '', 'object_id': '1010', 'state': 'T'}},
 '9': {'0': {'hl': '', 'object_id': '1193', 'state': 'T'},
       '1': {'hl': '', 'object_id': '1193', 'state': 'T'},
       '2': {'hl': '', 'object_id': '1193', 'state': 'T'}},
 'asset_no': '',
 'atags': {'0': {'tag': '$rackid_662'}, '1': {'tag': '$any_rack'}},
 'comment': '',
 'etags': {'21': {'id': '21',
                  'parent_id': '15',
                  'tag': 'DevIT',
                  'time': '1395166273',
                  'user': 'towens-admin'},
           '23': {'id': '23',
                  'parent_id': '9',
                  'tag': 'Internap SEF003',
                  'time': '1395166273',
                  'user': 'towens-admin'}},
 'has_problems': 'no',
 'height': '44',
 'id': '662',
 'isDeletable': '',
 'itags': {'15': {'id': '15',
                  'is_assignable': 'no',
                  'parent_id': '',
                  'refcnt': {'total': '0'},
                  'tag': 'IT Owner',
                  'trace': {}},
           '9': {'id': '9',
                 'is_assignable': 'no',
                 'parent_id': '',
                 'refcnt': {'total': '0'},
                 'tag': 'Site',
                 'trace': {}}},
 'location_id': '374',
 'location_name': 'Internap, SEF003',
 'mountedObjects': {'0': '590',
                    '1': '1010',
                    '10': '1201',
                    '11': '1202',
                    '12': '554',
                    '13': '949',
                    '14': '954',
                    '15': '1203',
                    '16': '1204',
                    '17': '1220',
                    '18': '1221',
                    '19': '1222',
                    '2': '1193',
                    '20': '1223',
                    '21': '1224',
                    '3': '1194',
                    '4': '1195',
                    '5': '1196',
                    '6': '1197',
                    '7': '1198',
                    '8': '1199',
                    '9': '1200'},
 'name': '13',
 'realm': 'rack',
 'row_id': '375',
 'row_name': 'B02-J'}

我需要以下列模式提取第一个键:

cabinet['25']['0']['object_id']

这是我的代码:

def get_RU(self, hostname):
        host_id = unicode(self.get_id(hostname))
        cab_no = int(self.depot[host_id]['rack_id'])
        cabinet = self.admin.get_rack(cab_no)
        cabinet_name = cabinet['name']
        for key in cabinet.keys():
            if type(cabinet[key]) == dict:
                for k in cabinet[key].keys():
                    if k == '0' and cabinet[key][k]['object_id'] == host_id:
                        return key, cabinet_name

我尝试做的是使用递归,或者找出一种重构代码的方法,使其更清晰。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

结构相当困难。我希望,我理解你的问题。

需求审核

您的数据隐藏了主机的身份(您的key),因此您的搜索结果为:

hostname - > host_id - > (柜子数据结构)[?key?]

具有适当key的条件是,(keydata)[“0”] [“object_id”] == host_id

什么可以改写

不要循环使用已知密钥

的项目

您可以简化:

for k in cabinet[key].keys():
   if k == '0' and cabinet[key][k]['object_id'] == host_id:
      pass #do something

为:

if cabinet[key]["0"]['object_id'] == host_id:
    pass #do something

值类型测试

您的值类型类型:

type(val) == dict

可以改写为:

isinstance(val, dict)

循环遍历字典中的键

for key in dct.keys():
    print key

通常写成:

for key in dct:
    print key

跳过dict类型

的测试

这取决于您的数据是否正确。如果你不能依赖它,请忽略它。

重写功能

这是你原来的功能:

def get_RU(self, hostname):
        host_id = unicode(self.get_id(hostname))
        cab_no = int(self.depot[host_id]['rack_id'])
        cabinet = self.admin.get_rack(cab_no)
        cabinet_name = cabinet['name']
        for key in cabinet.keys():
            if type(cabinet[key]) == dict:
                for k in cabinet[key].keys():
                    if k == '0' and cabinet[key][k]['object_id'] == host_id:
                        return key, cabinet_name

新版本:

def get_RU(self, hostname):
    host_id = unicode(self.get_id(hostname))
    cab_no = int(self.depot[host_id]['rack_id'])
    cabinet = self.admin.get_rack(cab_no)
    cabinet_name = cabinet['name']
    for key in cabinet:
        if cabinet[key]['0']['object_id'] == host_id:
            return key, cabinet_name

如果您确实无法阻止键值不是dict的问题,您可以添加try / catch

def get_RU(self, hostname):
    host_id = unicode(self.get_id(hostname))
    cab_no = int(self.depot[host_id]['rack_id'])
    cabinet = self.admin.get_rack(cab_no)
    cabinet_name = cabinet['name']
    for key in cabinet:
        try:
            if cabinet[key]['0']['object_id'] == host_id:
                return key, cabinet_name
        except (KeyError, TypeError):
            continue

更正数据结构

您应至少以这样的方式重新组织您的数据,即相同类型的结构共存并且不与其他结构混合。这样,您应该将键“0”,“1”,“2”等的所有值与文本值分开。这将使您不需要对dict类型进行测试,并且还可以使您的代码和数据更易于阅读。

结论

丑陋的数据结构使代码变得困难。尝试纠正数据结构,如果可以,最好将其转换为dict,其中键将为host_id,并为今天搜索的key值。