为了账号安全,请及时绑定邮箱和手机立即绑定

在嵌套的python词典和列表中查找所有出现的键

在嵌套的python词典和列表中查找所有出现的键

MM们 2019-08-26 15:44:22
在嵌套的python词典和列表中查找所有出现的键我有一个这样的字典:{ "id" : "abcde",   "key1" : "blah",   "key2" : "blah blah",   "nestedlist" : [      { "id" : "qwerty",       "nestednestedlist" : [          { "id" : "xyz",           "keyA" : "blah blah blah" },         { "id" : "fghi",           "keyZ" : "blah blah blah" }],       "anothernestednestedlist" : [          { "id" : "asdf",           "keyQ" : "blah blah" },         { "id" : "yuiop",           "keyW" : "blah" }] } ] }基本上是具有任意深度的嵌套列表,字典和字符串的字典。遍历此方法以提取每个“id”键的值的最佳方法是什么?我想实现相当于XPath查询,如“// id”。“id”的值始终是一个字符串。所以从我的例子来看,我需要的输出基本上是:["abcde", "qwerty", "xyz", "fghi", "asdf", "yuiop"]订单并不重要。
查看完整描述

3 回答

?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

我发现这个Q / A非常有趣,因为它为同样的问题提供了几种不同的解决方案。我使用了所有这些函数并使用复杂的字典对象对其进行了测试。我不得不从测试中取出两个函数,因为它们必须有许多失败结果,并且它们不支持返回列表或dicts作为值,这是我认为必不可少的,因为应该为几乎任何数据准备函数。


所以我通过timeit模块在100.000次迭代中抽取其他函数,输出结果如下:


0.11 usec/pass on gen_dict_extract(k,o)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

6.03 usec/pass on find_all_items(k,o)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

0.15 usec/pass on findkeys(k,o)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

1.79 usec/pass on get_recursively(k,o)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

0.14 usec/pass on find(k,o)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

0.36 usec/pass on dict_extract(k,o)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

所有函数都有相同的针搜索('logging')和相同的字典对象,其构造如下:


o = { 'temparature': '50', 

      'logging': {

        'handlers': {

          'console': {

            'formatter': 'simple', 

            'class': 'logging.StreamHandler', 

            'stream': 'ext://sys.stdout', 

            'level': 'DEBUG'

          }

        },

        'loggers': {

          'simpleExample': {

            'handlers': ['console'], 

            'propagate': 'no', 

            'level': 'INFO'

          },

         'root': {

           'handlers': ['console'], 

           'level': 'DEBUG'

         }

       }, 

       'version': '1', 

       'formatters': {

         'simple': {

           'datefmt': "'%Y-%m-%d %H:%M:%S'", 

           'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'

         }

       }

     }, 

     'treatment': {'second': 5, 'last': 4, 'first': 4},   

     'treatment_plan': [[4, 5, 4], [4, 5, 4], [5, 5, 5]]

}

所有功能都提供相同的结果,但时间差异是戏剧性的!该函数gen_dict_extract(k,o)是我的函数改编自这里的函数,实际上它非常类似于findAlfe 的函数,主要区别在于,我检查给定对象是否具有iteritems函数,以防在递归期间传递字符串:


def gen_dict_extract(key, var):

    if hasattr(var,'iteritems'):

        for k, v in var.iteritems():

            if k == key:

                yield v

            if isinstance(v, dict):

                for result in gen_dict_extract(key, v):

                    yield result

            elif isinstance(v, list):

                for d in v:

                    for result in gen_dict_extract(key, d):

                        yield result

所以这个变体是这里最快和最安全的功能。并且find_all_items速度非常缓慢,远远低于第二慢,get_recursivley而其余部分dict_extract则彼此接近。功能fun和keyHole唯一的工作,如果你正在寻找的字符串。


这里有趣的学习方面:)


查看完整回答
反对 回复 2019-08-26
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

d = { "id" : "abcde",
    "key1" : "blah",
    "key2" : "blah blah",
    "nestedlist" : [ 
    { "id" : "qwerty",
        "nestednestedlist" : [ 
        { "id" : "xyz", "keyA" : "blah blah blah" },
        { "id" : "fghi", "keyZ" : "blah blah blah" }],
        "anothernestednestedlist" : [ 
        { "id" : "asdf", "keyQ" : "blah blah" },
        { "id" : "yuiop", "keyW" : "blah" }] } ] } def fun(d):
    if 'id' in d:
        yield d['id']
    for k in d:
        if isinstance(d[k], list):
            for i in d[k]:
                for j in fun(i):
                    yield j

>>> list(fun(d))['abcde', 'qwerty', 'xyz', 'fghi', 'asdf', 'yuiop']


查看完整回答
反对 回复 2019-08-26
  • 3 回答
  • 0 关注
  • 687 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信