2014-01-05 57 views
0

我有一個json文件data_large大小爲150.1MB。該文件中的內容是[{"score": 68},{"score": 78}]。我需要從每個項目中找到獨特分數的列表。蟒蛇 - 從大的json文件中找到唯一的值很有效

這是我在做什麼: -

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. 

我可以print set(i['score'] for i in content)線更有效。目前需要執行201secs。它可以變得更有效率嗎?

+0

參見:[上CodeReview.SE這個問題( http://codereview.stackexchange.com/questions/38574/how-to-find-the-unique-values-from-the-json-file)。 – poke

回答

2

這會給你一組獨特的分數值(僅)作爲整數。您將需要150 MB的可用內存。它使用re.finditer()來解析,比json解析器(在我的電腦上)快三倍。

import re 
import time 
t = time.time() 
obj = re.compile('{.*?: (\d*?)}') 
with open('datafile.txt', 'r') as f: 
    data = f.read() 
s = set(m.group(1) for m in obj.finditer(data)) 
s = set(map(int, s)) 
print time.time() - t 

使用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)) 
+0

我試過了你的're.findall'代碼,並且它增加了很多時間效率。有趣的是注意到如此巨大的表現。我瞭解代碼,但我的問題是爲什麼它更快?請提供您的意見。 –

+0

'對於這個特定的任務,你唯一要做的就是提取分數 - 可能它更快,因爲它不需要弄清楚,並且創建(子)字符串表示的python對象的類型。 – wwii

-2

嘗試使用一組

set([x['score'] for x in scores]) 

例如

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

您建議提問者使用確切的代碼來詢問如何改進。這似乎沒有什麼幫助。 – Blckknght

+0

我用過發電機。使用發電機通常被認爲是有效的 –

+0

沒有注意到。抱歉。 – haki

1

我不認爲有任何方式大大改善的事情。緩慢的部分可能只是在某些時候你需要解析整個JSON文件。無論你是預先做好(使用json.load)還是一點一點地(從ijson.items消耗發生器時),最終都需要處理整個文件。

使用ijson的好處是您只需要在任何給定時間在內存中擁有少量數據。對於具有數百兆字節數據的文件,這可能無關緊要,但如果您的數據文件增長到千兆字節或更多,這將是一筆非常大的交易。當然,這也可能取決於您正在運行的硬件。如果您的代碼要在RAM有限的嵌入式系統上運行,那麼限制內存使用就顯得尤爲重要。另一方面,如果它要在高性能的服務器或工作站上運行,並且有大量的ram可用,那麼可能沒有任何理由阻止。因此,如果您不希望數據變得太大(相對於系統的RAM容量),則可以嘗試測試以確定是否使用json.load在開始時讀取整個文件,然後獲取唯一值與set是更快。我不認爲有任何其他明顯的捷徑。

0

在我的系統中,以下直接代碼在18秒內處理10,000,000個分數(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))