2014-11-14 15 views
19

Mam plik składa się z JSON, każda linia, i chcesz posortować plik przez odwrócenie update_time.Lista sortowania python json według wartości

przykładowy plik JSON:

{ "page": { "url": "url1", "update_time": "1415387875"}, "other_key": {} } 
{ "page": { "url": "url2", "update_time": "1415381963"}, "other_key": {} } 
{ "page": { "url": "url3", "update_time": "1415384938"}, "other_key": {} } 

chcą wyjście:

{ "page": { "url": "url1", "update_time": "1415387875"}, "other_key": {} } 
{ "page": { "url": "url3", "update_time": "1415384938"}, "other_key": {} } 
{ "page": { "url": "url2", "update_time": "1415381963"}, "other_key": {} } 

mój kod:

#!/bin/env python 
#coding: utf8 

import sys 
import os 
import json 
import operator 

#load json from file 
lines = [] 
while True: 
    line = sys.stdin.readline() 
    if not line: break 
    line = line.strip() 
    json_obj = json.loads(line) 
    lines.append(json_obj) 

#sort json 
lines = sorted(lines, key=lambda k: k['page']['update_time'], reverse=True) 

#output result 
for line in lines: 
    print line 

Kod działa poprawnie z przykładowego pliku JSON, ale jeśli JSON nie ma "update_time", spowoduje zgłoszenie wyjątku KeyError. Czy istnieją sposoby, aby to zrobić?

Odpowiedz

17

Odpowiedź powinna być oczywista: Napisz funkcję, która używa try...except do obsługi KeyError, a następnie użyj tego jako argumentu key zamiast swojej lambda.

def extract_time(json): 
    try: 
     # Also convert to int since update_time will be string. When comparing 
     # strings, "10" is smaller than "2". 
     return int(json['page']['update_time']) 
    except KeyError: 
     return 0 

# lines.sort() is more efficient than lines = lines.sorted() 
lines.sort(key=extract_time, reverse=True) 
7

Można użyć dict.get() o wartości domyślnej:

lines = sorted(lines, key=lambda k: k['page'].get('update_time', 0), reverse=True) 

Przykład:

>>> lines = [ 
...  {"page": {"url": "url1", "update_time": "1415387875"}, "other_key": {}}, 
...  {"page": {"url": "url2", "update_time": "1415381963"}, "other_key": {}}, 
...  {"page": {"url": "url3", "update_time": "1415384938"}, "other_key": {}}, 
...  {"page": {"url": "url4"}, "other_key": {}}, 
...  {"page": {"url": "url5"}, "other_key": {}} 
... ] 
>>> lines = sorted(lines, key=lambda k: k['page'].get('update_time', 0), reverse=True) 
>>> for line in lines: 
...  print line 
... 
{'other_key': {}, 'page': {'url': 'url1', 'update_time': '1415387875'}} 
{'other_key': {}, 'page': {'url': 'url3', 'update_time': '1415384938'}} 
{'other_key': {}, 'page': {'url': 'url2', 'update_time': '1415381963'}} 
{'other_key': {}, 'page': {'url': 'url4'}} 
{'other_key': {}, 'page': {'url': 'url5'}} 

Chociaż ja wciąż podążać za EAFP principle że Ferdinand sugerowane - w ten sposób możesz również obsługiwać przy braku klucza page. Znacznie łatwiej pozwolić mu się zawieść i poradzić sobie z nim, niż sprawdzać wszystkie rodzaje narożnych skrzynek.

+0

jak przypisać plik json do linii tak, że musi dynamicznie, jeśli mam 1 milion linii, to nie załaduje się poprawnie, dlatego –

4
#sort json 
lines = sorted(lines, key=lambda k: k['page'].get('update_time', 0), reverse=True) 
Powiązane problemy