2016-10-03 2 views
-1

파이썬을 사용하여 json 배열에서 값을 추출하려고합니다. 특정 날짜에 "energy" 값을 얻으려면 어떻게해야합니까? 여기에 JSON의 모습입니다 :조건부 파싱 json

parsed_json = json.loads(json) 

가 어떻게 "year":2016, "month":10, "day":2에 대한 "energy" 값을 추출합니다 : 사용 예를 들어

{ 
    "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 
    } 
    } 
} 

그래서?

+0

. 'json ='이 JSON 텍스트 문자열에 없다고 가정합니다. –

+1

여기에는 * 구문 분석에 대한 조건이 없습니다. 구문 분석 된 데이터 구조를 검색하여 조각을 추출하는 것은 조건부 구문 분석 ("활성 CS 연구"주제에서 제외)보다 많은 ** 쉬운 문제입니다. –

+0

그런데 이것은 다소 불행한 데이터 구조입니다. { "year": { "2016": { "10": { "1": 0.651, "2": 0.349, "3"} 일 경우 단일 값을 검색하는 것이 훨씬 더 효율적입니다. ": 0.481}}}' –

답변

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) 
+0

고맙습니다. 완벽하게 작동합니다. – Baobab

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))) 

출력 :

유효한 JSON 아닌
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