[英]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.