prolisk
@prolisk
Верстая. Криво.

Как убрать дубли по key в большом файле?

Имеется файл json на 8млн+ строк и 700+ мбайт размера, такого формата:

{'title':'7778', 'mes':'ruseo', 'coord': '755'}
{'title':'77789', 'mes':'ruseo', 'coord': '755'}
{'mes': 'seoru', 'title' : '7778', 'coord' : '-'}
{'mes': 'seoru', 'title' : '7778', 'coord' : '-'}

половина title вначале, половина в средине. Нужно убрать дубли по title, чтобы остались только уникальные.
Подскажите любой оперативный способ это сделать.
Сейчас обрабатываю на python.
1) json.loads и set (если списком) = memory error. (на сервере 64 гб ОЗУ)
2) открываю как текстовый файл, разбиваю, и по уникальности уже сверяю, но все очень долго. За 2 суток только 1,5 млн строк прошло.
(если детально:
Код
import json

with open(r'C:\json3toster.json', 'r', encoding="utf-8") as fp:
    ds = fp.readlines()

print(len(ds))
mem = []
for record in ds:
    name = record.replace('{','').split(',')
    for dat in name:
        dat2 = dat.split(': ')
        if dat2[0] == ' "title"':
            newline = dat2[1]
            if any(newline in lice for lice in mem):
                pass
            else:
                mem.append(record)
print(len(mem))
for newjs in mem:
    with open(r'd:/json_fin.json', 'a', encoding='utf-8') as fg:
        fg.write(newjs)

)

Изначально от дублей строк почистил через sort.
Можно любое решение, не обязательно питон.
Спасибо за любую подсказку.
  • Вопрос задан
  • 349 просмотров
Решения вопроса 1
adugin
@adugin Куратор тега Python
Вы делаете что-то ужасное. Особенно плох поиск по списку вместо множества. Сделайте так:
from ast import literal_eval as eval  # ast.literal_eval() безопасный, обычный eval() - нет

with open('input.txt', 'r') as fi, open('output.txt', 'w') as fo:
    cache = set()
    for line in fi:
        title = eval(line).get('title')
        if title not in cache:
            cache.add(title)
            fo.write(line)


Можно оригинально реализовать кэширование декоратором:
from ast import literal_eval as eval
from functools import lru_cache

@lru_cache(None)
def process(title):
    print(record, file=fo)

with open('input.txt', 'r') as fi, open('output.txt', 'w') as fo:
    for record in map(eval, fi):
        process(record['title'])


Ну и глянуть статистику кэша заодно:
>>> process.cache_info()
CacheInfo(hits=994960, misses=5040, maxsize=None, currsize=5040)
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
exibite777
@exibite777
Ведущий системный аналитик
Мне кажется Вы слишком замудрено подошли к вопросу
with open('input.txt', 'r') as fi, open('output.txt', 'w') as fo:
    print(*{line.split("title")[1].split("'")[2]: line for line in fi}.values(), 
            sep='', file=fo)
1 млн строк обработалось за 0:00:01.746256
Кроме того в своем вопросе Вы не задали крайне важные вопросы:
1. Что делать если остальные данные не совпадают, как мерджить результаты?
2. Какое из совпадений считать верным - первое или последнее?
Ответ написан
longclaps
@longclaps
как вариант можно попробовать так Говно вопрос:
import re

with open(r'C:\json3toster.json', 'r', encoding="utf-8") as fp:
    ds = fp.readlines()
d = {"'title'": 0, "'mes'": 1, "'coord'": 2}
print(len(ds))
findall, buf = re.compile(r"'[^']*'").findall, [''] * 3
for i, s in enumerate(ds):
    l = findall(s)
    while l:
        w = l.pop()
        buf[d[l.pop()]] = w
    ds[i] = '\t'.join(buf)
ds.sort()
a = ''
with open(r'd:/json_fin.json', 'a', encoding='utf-8') as fg:
    for s in ds:
        title, mes, coord = s.split('\t')
        if a != title:
            a = title
            fg.write(f"{{'title': {title} 'mes': {mes}, 'coord': {coord}}}\n")
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
14 дек. 2019, в 20:53
300 руб./в час
14 дек. 2019, в 20:52
4000 руб./за проект
14 дек. 2019, в 19:46
750 руб./в час