我正在尝试使用python从json数组中提取值。如何在特定日期获得"energy"
的值?这是json的样子:
{
"emeter": {
"get_daystat": {
"day_list": [
{ "year": 2016, "month": 10, "day": 1, "energy": 0.651000 },
{ "year": 2016, "month": 10, "day": 2, "energy": 0.349000 },
{ "year": 2016, "month": 10, "day": 3, "energy": 0.481000 }
],
"err_code": 0
}
}
}
例如,使用:
parsed_json = json.loads(json)
如何提取"energy"
的{{1}}值?
答案 0 :(得分:3)
parsed_json
将有一个python dict。您可以通过简单的线性搜索访问day_list
数组。
def get_energy_value_by_date(obj, year, month, day):
for value in obj['emeter']['get_daystat']['day_list']:
if value['year'] == year and value['month'] == month and value['day'] == day:
return value['energy']
energy = get_energy_value_by_date(parsed_json, 2016, 10, 2)
答案 1 :(得分:0)
您可以对数据进行线性搜索:
def get_energy(data, year, month, day):
for date in data['emeter']['get_daystat']['day_list']:
if(date['year'] == year
and date['month'] == month
and date['day'] == day):
return date['energy']
json_data = {
"emeter": {
"get_daystat": {
"day_list": [
{ "year": 2016, "month": 10, "day": 1, "energy": 0.651000 },
{ "year": 2016, "month": 10, "day": 2, "energy": 0.349000 },
{ "year": 2016, "month": 10, "day": 3, "energy": 0.481000 }
],
"err_code": 0
}
}
}
print('{:1.6f}'.format(get_energy(json_data, 2016, 10, 2))) # --> 0.349000
如果没有匹配日期,该函数将有效返回None
。
<强> *更新* 强>
如果您在"day_list"
和中有很多天,他们按照您的示例所示按日期排序(排序),则可以更快地利用它并执行二分搜索而不是线性搜索。 Python包含bisect
模块,可用于执行简单的二进制搜索。不幸的是,它中没有一个函数采用可选参数来控制比较,如sorted()
函数。
但是,可以通过查看模块的source code并编写自己的搜索功能来解决这个问题,如下所示:
from datetime import datetime
def keyed_bisect_left(a, x, lo=0, hi=None, keyfunc=lambda v: v):
"""Return the index where to insert item x in list a, assuming a is sorted.
Like bisect.bisect_left but allows a keyfunc to extract key from each item.
"""
x_key = keyfunc(x)
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi) // 2
if keyfunc(a[mid]) < x_key:
lo = mid+1
else:
hi = mid
return lo
def get_date(d):
return datetime(d['year'], d['month'], d['day'])
def get_energy2(data, year, month, day):
"""Locate the first day exactly equal to the given date."""
day_list = data['emeter']['get_daystat']['day_list']
target = {'year': year, 'month': month, 'day': day}
i = keyed_bisect_left(day_list, target, keyfunc=get_date)
# return energy value if date found
if i != len(day_list) and get_date(day_list[i]) == get_date(target):
return day_list[i]['energy']
raise ValueError('date not found')
print('{:1.6f}'.format(get_energy2(json_data, 2016, 10, 1)))
print('{:1.6f}'.format(get_energy2(json_data, 2016, 10, 2)))
print('{:1.6f}'.format(get_energy2(json_data, 2016, 10, 3)))
print('{:1.6f}'.format(get_energy2(json_data, 2016, 10, 4)))
输出:
0.651000
0.349000
0.481000
Traceback (most recent call last):
File "conditionally-parsing-json.py", line 67, in <module>
print('{:1.6f}'.format(get_energy2(json_data, 2016, 10, 4))) # --> ValueError
File "conditionally-parsing-json.py", line 62, in get_energy2
raise ValueError('date not found')
ValueError: date not found