2014-04-18 32 views
1

我有一個非常大的詞典列表(GB大小)從API獲取。我想用它作爲其他函數的查找表。在Python中有幾種對象持久化方法,但是你推薦如何在磁盤上存儲字典列表以便於查找和查找?作爲磁盤上的查找表的字典的大型列表

{ 
    "library_id": "7", 
    "set_id": "80344779", 
    "description": "Very long description 1 ...", 
    "value": "1" 
    }, 
    { 
    "library_id": "22", 
    "set_id": "80344779", 
    "description": "Very long description 2 ...", 
    "value": "1" 
    }, 
    { 
    "library_id": "24", 
    "set_id": "80344779", 
    "description": "Very long description 3 ...", 
    "value": "8" 
    }, 
+1

一個可能的答案:店裏的MongoDB然後用pyMongo – emeth

+1

作爲提示:在存儲它們之前將數值(fe library_id)轉換爲int。這需要相當少的空間 - 在任何提到的持久性解決方案中。 – dorvak

回答

1

您的數據似乎是正常的,即字典的鍵沒有變化,對吧?有人可能會簡單地使用像MongoDB這樣的基於文檔的解決方案,但我認爲一個簡單的基於SQL的數據庫可能更高效且易於實現。

替代品將是pickle模塊(不推薦用於真正大型的對象,因爲它們被加載到內存中)或shelve,它建立在pickle之上,但對於大型文件afaik更加高效(它們未被加載立刻進入你的記憶)。 shelve的好處是它的語法,它模仿pythons字典句法,應該很容易使用(參見鏈接)。而且不需要建立MongoDB或MySQL數據庫(這可能會變得複雜,至少在Windows上)。醃菜和擱架都是標準庫的一部分。

你也可以檢查datasets,它是一個易於使用的界面。它在引擎蓋下使用了一個sqlite-db。如果你處理的是大文件(比如說大於2 GB),我不會堅持使用數據集或擱置,而是使用像sqlalchemy(+ MySQL-DB)或MongoDB這樣更成熟的聲明,它的Python接口( PyMongo)

+0

謝謝dorvak!我要爲這個項目使用MongoDB + pyMongo。 – dust

2

的一種方式可能是建立一個模型(使用Django模型https://docs.djangoproject.com/en/dev/topics/db/models/)類,以匹配您的詞典字段,並保存在對象中的每個字典一樣

喜歡的東西:

from django.db import models 

class MyDict(models.model): 
    library_id = models.CharField(max_length=30) 
    set_id = models.CharField(max_length=30) 
    description = models.CharField(max_length=30) 

你可以將你的「library_id」作爲主鍵,如果它的唯一性,這將幫助你用library_id查找。

你也可以爲你的Google應用引擎的ndb api出於同樣的目的。 (如果您在Google App引擎上託管)。 https://developers.google.com/appengine/docs/python/ndb/

+0

謝謝@Nitin Verma,這是另一種解決這個問題的方法,我不知道它存在。值得一試儘快。 – dust

0

正如其他答案所示,值得研究打包的數據庫模型。如果你想要可移植性,你可以使用python輕鬆創建一個sqlite3數據庫。假設你的數據來自API和根本字典元素的列表,像你上面列出,一個最小工作示例會是什麼樣子:

import sqlite3 

# Create a database in memory, in practice you would save to disk 
conn = sqlite3.connect(':memory:') 

# Read in the data [omitted for brevity] 

cmd_create_table=''' 
CREATE TABLE api_data (
set_id  INTEGER, 
library_id INTEGER, 
description STRING, 
value  INTEGER); 
CREATE INDEX idx_api ON api_data (library_id, set_id); 
''' 
conn.executescript(cmd_create_table) 

cmd_insert = '''INSERT INTO api_data VALUES (?,?,?,?)''' 
keys = ["set_id","library_id","description","value"] 

for item in data: 
    val = [item[k] for k in keys] 
    conn.execute(cmd_insert, val) 

def lookup(library_id, set_id): 
    cmd_find = 'SELECT * FROM api_data WHERE library_id={} AND set_id={}' 
    cmd = cmd_find.format(library_id, set_id) 
    return conn.execute(cmd).fetchall() 

print lookup(22, 80344779) 

>>> [(80344779, 22, u'Very long description 2 ...', 1)] 
+0

儘管我在發佈問題後已經開始在MongoDB中實現這個功能,但這看起來像是一個非常優雅的解決方案。我認爲將它作爲SQL表執行會更麻煩。感謝您的示例代碼 - 絕對值得在未來的項目中嘗試。 – dust

+0

@dust mySQL可能會麻煩設置有時,但sqlite是非常容易和相當便攜的其他程序。 – Hooked