[英]Python dictionary with multiple keys pointing to same list in memory efficient way
我有這個獨特的要求,可以用這段代碼來解釋。 這是有效的代碼,但 memory 效率不高。
data = [[
"A 5408599",
"B 8126880",
"A 2003529",
],
[
"C 9925336",
"C 3705674",
"A 823678571",
"C 3205170186",
],
[
"C 9772980",
"B 8960327",
"C 4185139021",
"D 1226285245",
"C 2523866271",
"D 2940954504",
"D 5083193",
]]
temp_dict = {
item: index for index, sublist in enumerate(data)
for item in sublist
}
print(data[temp_dict["A 2003529"]])
out: ['A 5408599', 'B 8126880', 'A 2003529']
簡而言之,我希望子列表的每個項目都是可索引的,並且應該返回子列表。
上述方法有效,但是當數據很大時,它需要大量的 memory。 有沒有更好的 memory 和 CPU 友好的方式? 數據存儲為 JSON 文件。
編輯我嘗試了最大可能用例場景的答案(1000 個子列表,每個子列表中有 100 個項目,100 萬個查詢),這里是結果(10 次運行的平均值):
Method, Time (seconds), Extra Memory used
my, 0.637 40 Mb
deceze, 0.63 40 Mb
James, 0.78 200 kb
Pant, > 300 0 kb
mcsoini, forever 0 kb
你可以嘗試這樣的事情:
list(filter(lambda x: any(["C 9772980" in x]),data))
無需制作映射結構。
您實際上是在生成字典所需的時間/內存與掃描整個數據以查找動態方法所需的時間之間進行權衡。
如果您想要一個低 memory 方法,您可以使用 function 搜索每個子列表的值。 使用生成器將更快地為用戶獲得初始結果,但對於大型數據集,這在返回之間會很慢。
data = [[
"A 5408599",
"B 8126880",
"A 2003529",
],
[
"C 9925336",
"C 3705674",
"A 823678571",
"C 3205170186",
],
[
"C 9772980",
"B 8960327",
"C 4185139021",
"D 1226285245",
"C 2523866271",
"D 2940954504",
"D 5083193",
]]
def find_list_by_value(v, data):
for sublist in data:
if v in sublist:
yield sublist
for s in find_list_by_value("C 9772980", data):
print(s)
如評論中所述,僅基於第一個字母或前 2 或 3 個字符構建 hash 表可能是一個不錯的起點。 這將允許您構建子列表的候選列表,然后掃描它們以查看該值是否在子列表中。
from collections import defaultdict
def get_key(v, size=3):
return v[:size]
def get_keys(sublist, size=3):
return set(get_key(v, size) for v in sublist)
def find_list_by_hash(v, data, hash_table, size=3):
key = get_key(v, size)
candidate_indices = hash_table.get(key, set())
for ix in candidates:
if v in data[ix]:
yield data[ix]
# generate the small hash table
quick_hash = defaultdict(set)
for i, sublist in enumerate(data):
for k in get_keys(sublist, 3):
quick_hash[k].add(i)
# lookup a value by the small hash
for s in find_list_by_hash("C 9772980", data, quick_hash, 3):
print(s)
在此代碼quick_hash
需要一些時間來構建,因為您正在掃描整個數據結構。 但是,memory 占用空間會小很多。 您調整性能的主要參數是size
。 較小的尺寸將具有較小的 memory 占用空間,但在運行find_list_by_hash
時會花費更長的時間,因為您的候選池會更大。 您可以進行一些測試以查看適合您的數據的size
。 請注意,您的所有值都至少與size
一樣長。
試試這個,使用 pandas
import pandas as pd
df=pd.DataFrame(data)
rows = df.shape[0]
for row in range(rows):
print[[row]] #Do something with your data
這看起來很簡單的解決方案,即使您的數據變大,這也會有效地處理
我不完全確定這對於大量數據會如何表現,但您可以嘗試以下方式:
import pandas as pd
df = pd.DataFrame(data).T
df.loc[:, (df == 'A 2003529').any(axis=0)]
Out[39]:
0
0 A 5408599
1 B 8126880
2 A 2003529
3 None
4 None
5 None
6 None
編輯:基於對一些假的更大規模數據的快速測試,在時間方面似乎沒有好處。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.