Python—高效地从大型json文件中查找唯一值

Python—高效地从大型json文件中查找唯一值,python,json,large-files,Python,Json,Large Files,我有一个大小为150.1MB的json文件。文件中的内容类型为[{“score”:68},{“score”:78}]。我需要找到每个项目的唯一分数列表 这就是我正在做的:- import ijson # since json file is large, hence making use of ijson f = open ('data_large') content = ijson.items(f, 'item') # json loads quickly here as compared

我有一个大小为150.1MB的json文件。文件中的内容类型为
[{“score”:68},{“score”:78}]
。我需要找到每个项目的唯一分数列表

这就是我正在做的:-

import ijson  # since json file is large, hence making use of ijson

f = open ('data_large')
content = ijson.items(f, 'item') # json loads quickly here as compared to when json.load(f) is used.
print set(i['score'] for i in content) #this line is actually taking a long time to get processed.
我可以使
打印集(I内容中I的I['score'])
行更高效吗。目前执行需要201s。可以提高效率吗?

试着使用一套

set([x['score'] for x in scores])
比如说

>>> scores = [{"score" : 78}, {"score": 65} , {"score" : 65}]
>>> set([x['score'] for x in scores])
set([65, 78])

我不认为有任何方法可以改善很多事情。缓慢的部分可能只是因为在某个时候您需要解析整个JSON文件。无论您是提前(使用
json.load
)还是逐步(从
ijson.items
使用生成器),最终都需要处理整个文件

使用
ijson
的优点是,在任何给定时间,您只需要在内存中存储少量数据。这对于一个有大约100兆字节数据的文件来说可能并不重要,但是如果您的数据文件增长到千兆字节或更多,这将是一个非常重要的问题。当然,这也可能取决于您运行的硬件。如果您的代码要在RAM有限的嵌入式系统上运行,那么限制内存使用就更为重要。另一方面,如果它将运行在一个高性能的服务器或工作站上,并且有大量可用的ram,那么可能没有任何理由停止


因此,如果您不希望您的数据变得太大(相对于系统的RAM容量),您可以尝试测试,看看是否在开始时使用
json.load
读取整个文件,然后使用
set
获取唯一值更快。我认为没有任何其他明显的捷径。

在我的系统上,下面的简单代码在18秒内处理10000000个分数(139兆字节)。太慢了吗

#!/usr/local/cpython-2.7/bin/python

from __future__ import print_function

import json  # since json file is large, hence making use of ijson

with open('data_large', 'r') as file_:
    content = json.load(file_)
    print(set(element['score'] for element in content))

这将为您提供一组唯一的分数值(仅限整数)。您需要150 MB的可用内存。它使用re.finditer()进行解析,速度大约是json解析器(在我的计算机上)的三倍

使用re.findall()似乎也比json解析器快三倍左右,它大约消耗260 MB:

import re
obj = re.compile('{.*?: (\d*?)}')
with open('datafile.txt', 'r') as f:
    data = f.read()
s = set(obj.findall(data))

你是在建议提问者使用他正在询问如何改进的确切代码。这似乎没什么帮助,我用的是发电机。使用发电机通常被认为是有效的。我没有注意到。对不起,我尝试了你的
re.findall
代码,是的,它大大提高了时间效率。注意到如此大量的表演是很有趣的。我理解代码,但我的问题是为什么它更快?请就此提供您的意见。
对于此特定任务,您唯一要做的就是提取分数
-可能更快,因为它不需要计算和创建(子)字符串所代表的python对象类型。另请参阅:。
import re
obj = re.compile('{.*?: (\d*?)}')
with open('datafile.txt', 'r') as f:
    data = f.read()
s = set(obj.findall(data))