Как объединить два файла JSON в Python вместо вложенного цикла - PullRequest
0 голосов
/ 28 марта 2019

Каждый раз, когда я получаю 500 записей из файла file1, чтобы присоединиться к file2, который содержит более 100000 записей, это стоит две минуты !!

with open(file1,'r') as f1,open(file2,'r') as f2:
    a = json.load(f1)
    b = json.load(f2)
    list_a = []
    for i in range(len(a)):
        for n in range(len(b)):
            if b[n]["id"] == a[i]["id"]:
                list_a.append(dict(b[n], **a[i]))
with open(result,'w') as f3:
    json.dump(list_a, f3,sort_keys=True, ensure_ascii=False)

File1:

[{ "id":"1", "name":"Tom" }, 
{ "id":"2", "name":"Jim" }, 
{ "id":"3", "name":"Bob" }, 
{ "id":"4", "name":"Jeny" },  
{ "id":"5", "name":"Lara" }, 
{ "id":"6", "name":"Lin" }, 
{ "id":"7", "name":"Kim" }, 
{ "id":"8", "name":"Jack" }, 
{ "id":"9", "name":"Tony" }]

Файл 2:

[ { "id":"1", "Details":[ { "label":"jcc", "hooby":"Swimming" }, { "label":"hkt", "hooby":"Basketball" }, ] }, 
{ "id":"2", "Details":[ { "label":"NTC", "hooby":"Games" } ] } ]

Результат:

[ { "id":"1", "name":"Tom", "Details":[ { "label":"jcc", "hooby":"Swimming" }, { "label":"hkt", "hooby":"Basketball" }, ] }, 
{ "id":"2", "name":"Jim", "Details":[ { "label":"NTC", "hooby":"Games" } ] } ] 

Ответы [ 2 ]

0 голосов
/ 28 марта 2019

У меня нет опыта, чтобы знать, ускорит ли это это.Представленное ниже решение Евгения Ярмаша кажется более надежным.У меня также нет больших файлов для тестирования скорости, но вы можете попробовать и посмотреть, ускорит ли использование коллекций итерацию.Мне бы на самом деле было бы любопытно, если бы это что-то изменило:

File1 = [ { "id":"1", "name":"Tom" }, { "id":"2", "name":"Jim" }, { "id":"3", "name":"Bob" }, { "id":"4", "name":"Jeny" }, { "id":"5", "name":"Lara" }, { "id":"6", "name":"Lin" }, { "id":"7", "name":"Kim" }, { "id":"8", "name":"Jack" }, { "id":"9", "name":"Tony" } ]
File2 = [ { "id":"1", "Details":[ { "label":"jcc", "hooby":"Swimming" }, { "label":"hkt", "hooby":"Basketball" }, ] }, { "id":"2", "Details":[ { "label":"NTC", "hooby":"Games" } ] } ] 

from collections import defaultdict

d = defaultdict(dict)
for l in (File1, File2):
    for elem in l:
        d[elem['id']].update(elem)
Result = dict(d)
0 голосов
/ 28 марта 2019

Ваш код выполняется за O(N*M) время (где N == len(a) и M == len(b)), что слишком медленно для таких больших файлов.Вы можете запустить его в O(N + M) времени, сначала создав сопоставление для идентификаторов a и используя его для поиска совпадающих идентификаторов b, например:

import json

with open('file1') as f1, open('file2') as f2, open('file3', 'w') as f3:
    a = json.load(f1)
    b = json.load(f2)

    aid = {d['id']: d for d in a}
    list_a = [{k: v for d in (b_dict, aid[b_dict['id']]) for k, v in d.items()}
              for b_dict in b if b_dict['id'] in aid]

    json.dump(list_a, f3, sort_keys=True, ensure_ascii=False)

Если вы хотитекод для совместимости с Python 2.x, вы можете использовать словарь для объединения словарей (как показано выше).В Python 3.5+ вы можете просто использовать распаковка , например {**d1, **d2}.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...