【问题标题】:In Python, how to concisely get nested values in json data?在 Python 中,如何简洁地获取 json 数据中的嵌套值?
【发布时间】:2020-04-22 07:25:50
【问题描述】:

我从 JSON 加载数据并尝试提取任意嵌套值使用列表作为输入,其中列表对应于 连续子项的名称。我想要一个函数 get_value(data,lookup),它通过将 lookup 中的每个条目视为嵌套子项来从数据中返回值。

在下面的例子中,当lookup=['alldata','TimeSeries','rates']时,返回值应该是[1.3241,1.3233]

json_data = {'alldata':{'name':'CAD/USD','TimeSeries':{'dates':['2018-01-01','2018-01-02'],'rates':[1.3241,1.3233]}}}

def get_value(data,lookup):
    res = data
    for item in lookup:
        res = res[item]
    return res

lookup = ['alldata','TimeSeries','rates']
get_value(json_data,lookup)

我的例子有效,但有两个问题:

  1. 效率低下 - 在我的 for 循环 中,我将整个 TimeSeries 对象复制到 res,然后将其替换为费率列表. 正如@Andrej Kesely 解释的那样,res 是每次迭代的引用,因此不会复制数据。
  2. 不简洁 - 我希望能够找到一种简洁的(例如一两行)使用列表理解语法之类的方法来提取数据

【问题讨论】:

  • 我觉得不错,为什么觉得效率低?您没有在循环中复制任何内容,res 变量仅包含对对象的引用。
  • @AndrejKesely - 谢谢,我没有意识到 res 是一个参考,只是用res = json_data; res = res['alldata']; print(json_data['alldata'] is res) 确认了它。这意味着效率低下不是问题,只是简洁

标签: json python-3.x dictionary


【解决方案1】:

如果你想要单线并且你使用的是 Python 3.8,你可以使用赋值表达式(“walrus operator”):

json_data = {'alldata':{'name':'CAD/USD','TimeSeries':{'dates':['2018-01-01','2018-01-02'],'rates':[1.3241,1.3233]}}}

def get_value(data,lookup):
    return [data:=data[item] for item in lookup][-1]

lookup = ['alldata','TimeSeries','rates']
print( get_value(json_data,lookup) )

打印:

[1.3241, 1.3233]

【讨论】:

  • 这看起来很聪明 - 谢谢!我没有使用 python 3.8,但在升级时会注意这一点。我刚刚为原始问题添加了一个扩展来定义 replace_value() (或者我应该发布一个新问题?[我对 StackOverflow 比较陌生])
  • @maurera 最好关闭这个问题(批准你最喜欢的答案)并写一个新的 :) 并欢迎堆栈溢出 :)
【解决方案2】:

我认为没有循环就无法做到这一点,但你可以在这里使用 reducer 来增加可读性。

functools.reduce(dict.get, lookup, json_data)

【讨论】:

  • 这很简洁 - 谢谢!我希望在没有导入语句的情况下使其简洁,但这似乎不可能
  • Python3 转换仍然让我有些困惑,我认为 reduce 曾经很原始。
猜你喜欢
  • 2020-04-22
  • 2020-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
  • 2020-04-29
相关资源
最近更新 更多