Py学习  »  Python

python方法1变量嵌套字典

Eran Moshe • 6 年前 • 1870 次点击  

我发现这类问题很难命名,但肯定是个简单的问题,我遗漏了一些基本的东西。

假设我有以下python dict():

import json

dct = dict()
dct['hits'] = dict()
dct['hits']['hits'] = dict()
dct['hits']['hits']['a'] = 'b'
dct['hits']['hits']['b'] = 'c'
dct['aggregations'] = dict()
dct['aggregations']['a'] = 1
dct['aggregations']['b'] = 2

print(json.dumps(dct, indent=2))

{
  "hits": {
    "hits": {
      "a": "b",
      "b": "c"
    }
  },
  "aggregations": {
    "a": 1,
    "b": 2
  }
}

这看起来可能很熟悉,因为它是elasticsearch返回结果的结构。

我正在构建一个使用该结果的函数。但有时我想接近 dct['hits']['hits'] 有时我想接近 dct['aggregations'] .

自然地,我会使用一个带有变量的函数来建议我要访问哪个字段,如下所示:

def foo(field):
    return dct[field]

如果 field='aggregations' 一切都很好。但如果我想让这个领域 ['hits']['hits'] ?


一种解决方法(但很难看),迭代方法:

def foo(fields=('hits','hits')):
    wanted = dct
    for field in fields:
        wanted = wanted[field]
    return wanted

a = foo()
a
Out[47]: {'a': 'b', 'b': 'c'}
a = foo(('aggregations',))
a
Out[51]: {'a': 1, 'b': 2}

我试图修改的实际函数:

def execute_scroll_query(es_client, query, indexes):
    try:
        response = es_client.search(index=indexes, scroll='2m', size=1000, body=query)
        scroll_size = len(response['hits']['hits'])
        sid = response['_scroll_id']
        while scroll_size > 0:
            try:
                for hit in response['hits']['hits']:
                    yield hit
                response = es_client.scroll(scroll_id=sid, scroll='2m')
                sid = response['_scroll_id']
                scroll_size = len(response['hits']['hits'])
            except Exception:
                print("Unexpected Exception while scrolling")
    except Exception:
        print("Unexpected Exception while fetching")
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/40817
 
1870 次点击  
文章 [ 3 ]  |  最新文章 6 年前
Dipen Dadhaniya
Reply   •   1 楼
Dipen Dadhaniya    6 年前

尝试做:

dct = dict()
dct['hits'] = dict()
dct['hits']['hits'] = dict()
dct['hits']['hits']['a'] = 'b'
dct['hits']['hits']['b'] = 'c'
dct['aggregations'] = dict()
dct['aggregations']['a'] = 1
dct['aggregations']['b'] = 2


def foo(dct, *fields):
    n = len(fields)

    for idx in range(n):
        if idx == n - 1:
            return dct[fields[idx]]
        else:
            dct = dct[fields[idx]]


print(foo(dct, 'hits'))    
print(foo(dct, 'hits', 'hits'))
print(foo(dct, 'hits', 'hits', 'a'))
print(foo(dct, 'aggregations'))
print(foo(dct, 'aggregations', 'a'))
Iain Shelvington
Reply   •   2 楼
Iain Shelvington    6 年前

此函数将递归查找传递给它的字典中的键。 d 并返回上次成功的查找

def get_nested(d, key):
    result = d.get(key)
    if isinstance(result, dict):
        return result or get_nested(result, key)
    return result

可以这样称呼

get_nested(dct, 'hits')
get_nested(dct, 'aggregations')
DYZ
Reply   •   3 楼
DYZ    6 年前

你可以使用 functools.reduce ,但在幕后,它使用的是迭代,并且可能不如显式迭代有效:

from functools import reduce

def foo(d, keys):
    return reduce(lambda x, y: x[y], keys, d)

foo(dct, ['hits', 'hits', 'a'])
#'b'