python中无限遍历在多维嵌套字典、列表的JSON中获取路径path跟对应的值——find_path

    很多时候在对json转码后,发现数据都是列表字典循环嵌套,在敲代码时想以dict['key']这种格式得到自己想要的包裹多层的数据,特么再看看,又字典又列表的,难道要靠自己肉眼一个个寻找编写,再测试错对与否吗?如果是想要某个key对应的value呢?

真鸡儿痛苦,网上搜寻了一大堆,都没我想要的,要不是纯字典,要不只能拿到value值,我想要的是具体路径啊!

没把法,只能自己强上了!本来3个函数就能搞定了,根据要找的value值得到该值的具体路径,但是后面又想到有时是要根据key值得到对应的value,而且在镶嵌字典里,一样名字的key应该不少啊,最好还能返回要找的key的具体路径跟它对应的值,具体看代码

要点:1.isinstance(target, dict) 判断str类型

     2.list.index(‘a') 得出元素所在的位置

class find_path():
    def find_value_path(self,target, value, tmp_list ):
        '''输入字典的值/列表的元素,以list返回所对应的key/posi,跟所在的字典/列表
                                          [key,dict,posi,list,key,dict........]
        '''
        if isinstance(target, dict):         #判断了它是字典
            dict1 = target
            for k,v in dict1.items():        #遍历字典
                if str(value)==str(v):       #如果某个value就是要找的,就把k,整个dict放进tmp_list
                    tmp_list.append(str([k]))
                    tmp_list.append(dict1)
                else:
                    self.find_value_path(v, value, tmp_list)#value不是要找的,那么对这个value调用自身进行遍历

        elif isinstance(target, (list, tuple)):  #判断了它是列表
            var=target
            for each in var:                     #遍历列表
                 if str(each)==str(value):       #如果某个元素就是要找的,就把位置posi,整个list放进tmp_list
                    posi=var.index(each)
                    tmp_list.append(str([posi]))
                    tmp_list.append(var)
                 else:
                     self.find_value_path(each, value, tmp_list)#此元素不是要找的,那么对这个元素调用自身进行遍历
        return tmp_list

    def find_key_path(self,target, key, tmp_list):
        '''输入字典的key,以list返回所对应的key,所在的字典
                        [key,dict,key,dict........]'''
        if isinstance(target, dict):                     #find_value_path差不多,不过只当所查询的是key才会返回
            dict1 = target
            for k,v in dict1.items():
                if str(key)==str(k):
                    tmp_list.append(str([k]))
                    tmp_list.append(dict1)
                else:
                    self.find_key_path(v, key, tmp_list)

        elif isinstance(target, (list, tuple)):
            var=target
            for each in var:
                self.find_key_path(each, key, tmp_list)
        return tmp_list

    def get_path(self,target, objkey,path):
        ''' (key所在的dict)作为查询目标,不断的以上一层(所在的list/dict)作为查询目标调用自身,
            直到查询的上一层就是整个文本时,就输出每次调用自身所对应的key/posi组成的path
        :param target: json_text
        :param objkey: key所在的dict
        :param path:  对应的key
        :return:      完整路径
        '''
        if objkey==target:
            return ''.join(path[::-1])  #因为是list,先翻转再join合并,
        else:
            list1=self.find_value_path(target,objkey,[])  #返回的list应该只有2个元素[key,小dict],也不可能是空[]
            print('要查找的value所在的字典/列表一模一样的有%d个呢!!' % (len(list1) / 2)) if len(list1) > 2 else None
            path.append(list1[0])
            return self.get_path(target, list1[1], path) #循环自身

    def remove_the_same(self,list):
        '''[key,dict,posi,list,key,dict.....]形式传入
            去重(因为有些key所在的dict是一模一样的)
            返回[[key,dict],[posi,list],[key,dict]....]
        '''
        list1=[]
        for i in range(0, len(list), 2):
            r = list[i:i + 2]
            list1.append(r)
        list2 = []
        [list2.append(i) for i in list1 if not i in list2]
        return list2

    def print_all_path(self,target,find_list):
        '''步骤:1.remove_the_same(),去重,返回[[key,dict],[posi,list],[key,dict]....]
               2.循环[key,dict],再find_value_path()判断,如果还有重复,那么就对这些重复的循环,get_path()得出路径
没重复,直接get_path()得出路径
        :param target: json_text
        :param find_list: [key,dict,posi,list,key,dict.....]
        '''
        find_list = self.remove_the_same(find_list) #去重,返回[[key,dict],[posi,list],[key,dict]....]
        for key_dict in find_list:          # 循环各组key+dict————[key,dict]
            second_dict = self.find_value_path(target, key_dict[1], [])#判断key所在的dict是否有一模一样的
            #整个dict作为要查询的,返回[posi(dict所在),listposi(dict所在),list...]
            if len(second_dict) > 2:                              #判断出有多个相同的dict
                second_list = self.remove_the_same(second_dict)       #返回[[key,dict],[posi,list],[key,dict]....]
                for key_dict2 in second_list:                    #每个相同的dict分别求出路径
                    r = self.get_path(target, key_dict2[1], [key_dict[0], key_dict2[0]])  # 得出符合条件的path
                    print(r, '\n', eval('target' + r), '\n')             #第三个参数就是[key,上一层posi]
            else:
                r = self.get_path(target, key_dict[1], [key_dict[0]])  # key所在的dict独一无二,直接get_path
                print(r, '\n', eval('target' + r), '\n')


    def work(self,target, value):
        '''输入txt,需要查找的value,返回每个符合要求的path
        '''
        print('正在查找的是:%s'% value,'\n','*'*80)       #[key,dict,posi,list,key,dict.....]
        value_list = self.find_value_path(target, value, [])   #返回查找的value对应的key、所在dict组成的list
        key_list=   self.find_key_path(target, value, [])     #返回查找的key、            所在dict组成的list

        if value_list==[]:print('find_value_path——————这不是字典的值/列表的元素吧!找不到的!')
        else:print('find_value_path——————以《%s》为字典的值/列表的元素查到的具体路径在下面:'%value)#找不到!
        self.print_all_path(target, value_list)            #打印出key的路径,value
        print('='*80)
        if key_list==[]:print('find_key_path————————这不是字典的key!找不到的!')
        else:print('find_key_path————————以《%s》为字典的key查到的具体路径跟value在下面:'%value)
        self.print_all_path(target, key_list)            #打印出key的路径,value


思路,例如在下面文段:
# rr={'skin_imgs':
#     "[
#     {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cf96438b3.jpeg', 'skin_name': '冰雪之华'},
#     {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfaca937b.jpeg', 'skin_name': '精灵公主'},
#     {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfc62223c.jpeg', 'skin_name': '偶像歌手'},
#     {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfd3af958.jpeg', 'skin_name': '凤凰于飞'},
#     {'big_img': 'http://pic.wankacn.com/2018-03-12_5aa63988e13e9.jpeg', 'skin_name': '幻想奇妙夜'}
#     ]"}
# 查询'冰雪之华'
# 1.find_value_path()---→[
#                          ['skin_name'],
#                         '{'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cf96438b3.jpeg', 'skin_name': '冰雪之华'}'
#                         ]
# 2.find_value_path()---→[
#                            [0],
#                         "[{'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cf96438b3.jpeg', 'skin_name': '冰雪之华'},
#                         {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfaca937b.jpeg', 'skin_name': '精灵公主'},
#                         {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfc62223c.jpeg', 'skin_name': '偶像歌手'},
#                         {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfd3af958.jpeg', 'skin_name': '凤凰于飞'},
#                         {'big_img': 'http://pic.wankacn.com/2018-03-12_5aa63988e13e9.jpeg', 'skin_name': '幻想奇妙夜'}]"
#                         ]
# 3.最后find_value_path()---→[
#                             ['skin_imgs'],
#                             {'skin_imgs':
#                              "[ {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cf96438b3.jpeg', 'skin_name': '冰雪之华'},
#                                 {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfaca937b.jpeg', 'skin_name': '精灵公主'},
#                                 {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfc62223c.jpeg', 'skin_name': '偶像歌手'},
#                                 {'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfd3af958.jpeg', 'skin_name': '凤凰于飞'},
#                                 {'big_img': 'http://pic.wankacn.com/2018-03-12_5aa63988e13e9.jpeg', 'skin_name': '幻想奇妙夜'}
#                                 ]"}
#                             ]
# 把第一个参数key/posi整合起来,就是路径了:['skin_imgs'][0]['skin_name']

具体例子:

if __name__ == '__main__':
    dict1={'a':5,'recommend_summoner_skill_tips': '闪现:向指定方向位移一段距离', 'text_price': '', 'be_restrained_hero': [{'hero_id': '3', 'name': '赵云', 'icon': 'http://pictest.wankacn.com/2017-04-26_59005ecc2eda6.png'}, {'hero_id': '24', 'name': '宫本武藏', 'icon': 'http://pictest.wankacn.com/2017-04-26_59005ee432c52.png'}, {'hero_id': '39', 'name': '韩信', 'icon': 'http://pictest.wankacn.com/2017-04-26_59005eff2e35f.png'}], 'rec_inscriptions': [{'title': 'four', 'list': [{'name': '阳炎', 'icon': 'http://pictest.wankacn.com/2017-04-27_5901c32aec40d.png', 'attrs': '法术攻击+2.5|法术穿透+1.4', 'level': '4'}, {'name': '渴血', 'icon': 'http://pictest.wankacn.com/2017-04-27_5901c33051946.png', 'attrs': '法术攻击+1.4|法术吸血+0.8%|法术防御+1.6', 'level': '4'}, {'name': '侵蚀', 'icon': 'http://pictest.wankacn.com/2017-04-27_5901c3367da4c.png', 'attrs': '法术攻击+0.9|法术穿透+3.8', 'level': '4'}]}, {'title': 'five', 'list': [{'name': '圣人', 'icon': 'http://pictest.wankacn.com/2017-04-27_5901c32b7c6eb.png', 'attrs': '法术攻击+5.3', 'level': '5'}, {'name': '轮回', 'icon': 'http://pictest.wankacn.com/2017-04-27_5901c3325134d.png', 'attrs': '法术攻击+2.4|法术吸血+1%', 'level': '5'}, {'name': '怜悯', 'icon': 'http://pictest.wankacn.com/2017-04-27_5901c3384f95c.png', 'attrs': '冷却缩减-1%', 'level': '5'}]}], 'skill_list': [{'attrs': [], 'intro': '被动', 'description': '被动:王昭君脱离战斗后会获得可抵免450<span style="color:#6edbc8">(+52%法术加成)</span>点伤害的寒冰护盾,护盾破裂时对附近敌人造成一次冰霜冲击,造成450<span style="color:#6edbc8">(+52%法术加成)</span><span style="color:#7575d9">法术伤害</span>与减速效果;寒冰护盾有3秒的回复冷却时间', 'mana_cost': '', 'cd': '', 'tags': '法术', 'name': '冰封之心', 'icon': 'http://pic.wankacn.com/2017-08-28_59a37c3ac17e6.png'}, {'attrs': ['基础伤害|400|480|560|640|720|800'], 'intro': '主升', 'description': '王昭君操控碎裂冰晶绽开,对范围内的敌军造成400<span style="color:#6edbc8">(+65%法术加成)</span><span style="color:#7575d9">法术伤害</span>与减速,并获得他们的视野持续2', 'mana_cost': '80', 'cd': '5', 'tags': '法术/控制', 'name': '凋零冰晶', 'icon': 'http://pic.wankacn.com/2017-08-28_59a37c3de40b4.png'}, {'attrs': ['基础伤害|250|280|310|340|370|400', '冷却时间|10|9.2|8.4|7.6|6.8|6'], 'intro': '副升', 'description': '王昭君引领寒霜之力,一定时间后将范围内敌人冰冻并造成250<span style="color:#6edbc8">(+47%法术加成)</span><span style="color:#7575d9">法术伤害</span>;被动:对被冰冻的敌人造成额外250<span style="color:#6edbc8">(+50%法术加成)</span><span style="color:#7575d9">法术伤害</span>', 'mana_cost': '80', 'cd': '8', 'tags': '法术/控制', 'name': '禁锢寒霜', 'icon': 'http://pic.wankacn.com/2017-08-28_59a37c4140712.png'}, {'attrs': ['基础伤害|300|375|450', '冷却时间|50|45|40'], 'intro': '有大点大', 'description': '王昭君召唤寒冬之力,在指定位置降下暴风雪对范围内敌人每次打击造成300<span style="color:#6edbc8">(+50%法术加成)</span><span style="color:#7575d9">法术伤害</span>与减速,期间获得600护甲加成', 'mana_cost': '150', 'cd': '50', 'tags': '法术/控制', 'name': '凛冬已至', 'icon': 'http://pic.wankacn.com/2017-08-28_59a37c4495707.png'}], 'skill_tips': '使用凋零冰晶使对方减速后再其移动方向的前方一小段距离使用禁锢寒霜。接着立刻贴近使用凛冬已至,配合被动对敌方打出成吨伤害', 'hero_id': '40', 'half_img': 'http://pic.wankacn.com/2017-08-28_59a3840dd8625.png', 'recommend_summoner_skill': [{'name': '闪现', 'icon': 'http://pictest.wankacn.com/2017-04-27_5901deac66009.jpeg', 'description': '120CD:向指定方向位移一段距离'}], 'ticket_price': '588', 'type': ['2'], 'big_img': 'http://pic.wankacn.com/2017-08-28_59a38313260bb.png', 'restrained_hero': [{'hero_id': '10', 'name': '刘禅', 'icon': 'http://pictest.wankacn.com/2017-04-26_59005ed4dfde6.png'}, {'hero_id': '23', 'name': '典韦', 'icon': 'http://pictest.wankacn.com/2017-04-26_59005ee344db8.png'}, {'hero_id': '48', 'name': '亚瑟', 'icon': 'http://pictest.wankacn.com/2017-04-26_59005f0e9459e.png'}], 'gold_price': '8888', 'levels': {'attack': '3', 'skill': '10', 'survival': '2', 'difficulty': '6'}, 'name': '王昭君', 'hero_tips': '灵巧走位。尽量不要离敌方太近和太远,太近容易被贴身打击。太远冰冻住以后还没过去对方就解冻了。最好是等待别人与我方火并不能抽身离开时使用禁锢寒霜,给对方一个意想不到的绝望', 'equip_choice': [{'title': 'KPL职业出装', 'description': '这是KPL职业联赛中AG超玩会.老帅的出装。暴力输出,需要注意入场时机。', 'list': [{'icon': 'http://pictest.wankacn.com/2017-04-28_5903166adc5c9.jpeg', 'equip_id': '40'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_59031675e2f15.jpeg', 'equip_id': '75'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166b10ebe.jpeg', 'equip_id': '41'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166b83498.jpeg', 'equip_id': '43'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166c6d0eb.jpeg', 'equip_id': '48'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166c96be0.jpeg', 'equip_id': '49'}]}, {'title': 'KPL职业出装', 'description': '这是KPL职业联赛中QGhappy.Cat的出装。团队收益装备,梦魇之牙克制地方回血英雄。', 'list': [{'icon': 'http://pictest.wankacn.com/2017-04-28_5903166ab272c.jpeg', 'equip_id': '39'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_59031676397b3.jpeg', 'equip_id': '76'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166adc5c9.jpeg', 'equip_id': '40'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166b10ebe.jpeg', 'equip_id': '41'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166b5c100.jpeg', 'equip_id': '42'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166c96be0.jpeg', 'equip_id': '49'}]}, {'title': '强力消耗装', 'description': '这套装备靠减CD及回蓝,消耗对面英雄。冰霜法杖便宜、增加血量,可以让王昭君更稳健地对线,被动减速配合王昭君2技能很容易创造杀敌机会。', 'list': [{'icon': 'http://pictest.wankacn.com/2017-04-28_5903166c42ac0.jpeg', 'equip_id': '47'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_59031676397b3.jpeg', 'equip_id': '76'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166bda9f0.jpeg', 'equip_id': '45'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166b10ebe.jpeg', 'equip_id': '41'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166bb25f7.jpeg', 'equip_id': '44'}, {'icon': 'http://pictest.wankacn.com/2017-04-28_5903166c96be0.jpeg', 'equip_id': '49'}]}], 'partner_hero': [{'hero_id': '2', 'name': '小乔', 'icon': 'http://pictest.wankacn.com/2017-04-26_59005ecad0a65.png'}, {'hero_id': '5', 'name': '妲己', 'icon': 'http://pictest.wankacn.com/2017-04-26_59005ecec7ee2.png'}, {'hero_id': '30', 'name': '武则天', 'icon': 'http://pictest.wankacn.com/2017-04-26_59005eed6c76f.png'}], 'melee_tips': '在团战开始前期的迂回还没开始火并的时候跟在团后面用凋零冰晶对敌方进行骚扰和消耗,待开团开始后往人堆里放禁锢寒霜。总能冻住两个以上。接着使用凛冬已至再闪现过去。给对方一个沉重的打击。禁锢寒霜尽量瞄准输出类英雄那样才能凸显凛冬已至的爆炸伤害的效果', 'history_intro': '昭君,西汉元帝时宫人。《汉书·元帝纪》记载:竟宁元年春,匈奴乎韩邪单于来朝,元帝赐单于待诏掖庭王樯为阏氏。《后汉书》又记王昭君,字嫱。她和亲匈奴后,号宁胡阏氏', 'background_story': '北方草原上,生活着凶悍的北夷部族,时常冲击长城进行掠夺。陷入内乱的诸侯们不得不送去粮食,布匹与和亲的公主换来停战协议。 \r\n北夷人将公主送往圣地——凛冬之海,献祭给神明作为新娘。久而久之,这演变成一项残忍神圣的传统。 \r\n然而数百年后,统治者们认为不再需要盟约,开始谋划残酷的阴谋:他们乘人们举行祭典毫无防备之际血洗草原,还想夺取蛮夷们献给神明的宝藏。 \r\n刽子手们如愿以偿。他们发出欢呼,忙碌着将成堆黄金带回中原。暴风雪突如其来,随之是浩大的雪崩。 \r\n是北夷人神明的愤怒吗?刚刚还不可一世的士兵哀嚎着逃窜。然而归去的路已被冰雪封锁。他们像琥珀中的小虫般挣扎,眼睁睁看着自己的身躯被冰封进透明的棺材。 \r\n幸存的北夷人从藏身之处走出来,簇拥着他们的公主——王昭君。她高雅,美丽,明亮的双眸饱含哀伤,纤长的手指拂过故乡来客们冰冷狰狞的脸庞。\r\n告诉我,故乡的梅花开了吗?”', 'skin_imgs': [{'skin_name': '冰雪之华', 'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cf96438b3.jpeg'}, {'skin_name': '精灵公主', 'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfaca937b.jpeg'}, {'skin_name': '偶像歌手', 'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfc62223c.jpeg'}, {'skin_name': '凤凰于飞', 'big_img': 'http://pic.wankacn.com/2017-08-29_59a4cfd3af958.jpeg'}, {'skin_name': '幻想奇妙夜', 'big_img': 'http://pic.wankacn.com/2018-03-12_5aa63988e13e9.jpeg'}], 'title': '冰雪之华', 'diamond_price': '0'}
    d=find_path()
    d.work(dict1,'name')
 
 
输出:

正在查找的是:name 
 ********************************************************************************
find_value_path——————这不是字典的值/列表的元素吧!找不到的!
================================================================================
find_key_path————————以《name》为字典的key查到的具体路径跟value在下面:
['be_restrained_hero'][0]['name'] 
 赵云 
['be_restrained_hero'][1]['name'] 
 宫本武藏 
['be_restrained_hero'][2]['name'] 
 韩信 
['name'] 
 王昭君 
['rec_inscriptions'][0]['list'][0]['name'] 
 阳炎 
['rec_inscriptions'][0]['list'][1]['name'] 
 渴血 
['rec_inscriptions'][0]['list'][2]['name'] 
 侵蚀 
['rec_inscriptions'][1]['list'][0]['name'] 
 圣人 
['rec_inscriptions'][1]['list'][1]['name'] 
 轮回 
['rec_inscriptions'][1]['list'][2]['name'] 
 怜悯 
['recommend_summoner_skill'][0]['name'] 
 闪现 
['skill_list'][0]['name'] 
 冰封之心 
['skill_list'][1]['name'] 
 凋零冰晶 
['skill_list'][2]['name'] 
 禁锢寒霜 
['skill_list'][3]['name'] 
 凛冬已至 
['restrained_hero'][0]['name'] 
 刘禅 
['restrained_hero'][1]['name'] 
 典韦 
['restrained_hero'][2]['name'] 
 亚瑟 
['partner_hero'][0]['name'] 
 小乔 
['partner_hero'][1]['name'] 
 妲己 
['partner_hero'][2]['name'] 
 武则天 
ps:这是我第一次把自己的代码展示给别人看,注释肯定是惨不忍睹了,代码也可能很繁琐,希望各位高手能提个建议,谢谢哦


猜你喜欢

转载自blog.csdn.net/qq_38282706/article/details/79695658