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.
Можно любое решение, не обязательно питон.
Спасибо за любую подсказку.
  • Вопрос задан
  • 336 просмотров
Решения вопроса 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")
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
от 100 000 до 150 000 руб.
от 150 000 до 200 000 руб.
Alytics Зеленоград
от 100 000 до 130 000 руб.
11 нояб. 2019, в 22:15
4000 руб./за проект
11 нояб. 2019, в 22:12
1000 руб./за проект
11 нояб. 2019, в 21:54
1 руб./за проект