根据大量的字典更新字典
Updating dictionaries based on huge list of dicts
我有一个巨大的(大约 350k 个元素)字典列表:
lst = [
{'data': 'xxx', 'id': 1456},
{'data': 'yyy', 'id': 24234},
{'data': 'zzz', 'id': 3222},
{'data': 'foo', 'id': 1789},
]
另一方面,我收到了一个又一个缺失值的字典(大约 550k)(不是每个字典都缺失这个值),我需要更新它们:
example_dict = {'key': 'x', 'key2': 'y', 'id': 1456, 'data': None}
收件人:
example_dict = {'key': 'x', 'key2': 'y', 'id': 1456, 'data': 'xxx'}
我需要获取每个字典并在列表中搜索以匹配 'id' 并更新 'data'。这样做需要很长时间才能处理:
if example_dict['data'] is None:
for row in lst:
if row['id'] == example_dict['id']:
example_dict['data'] = row['data']
有没有办法构建一个结构化的分块数据,例如10k 值并告诉传入的字典在哪个块中搜索 'id'?或者任何其他优化方法?感谢任何帮助,保重。
使用字典而不是线性搜索列表。
第一个重要的优化是通过 lst
删除线性搜索,方法是构建一个索引为 id 并指向行
的字典
例如,如果您有足够的 RAM 来保存内存中的所有行,这将比您的代码快很多:
row_dict = {row['id']: row for row in lst}
if example_dict['data'] is None:
if example_dict['id'] in row_dict:
example_dict['data'] = row_dict[example_dict['id']]['data']
无论您是按 10k 块处理行还是一次性处理所有行,此改进都与您相关,因为字典查找时间是恒定的,而不是 lst
的线性大小。
制作您自己的分块过程
接下来你问“有没有办法构建一个结构化的分块数据......”。是的,一点没错。如果数据太大而无法放入内存,请编写一个 first pass 函数,将基于 id 的输入分成几个临时文件。如果顺序不相关,它们可以基于 ID 的最后两位数字,或者如果您愿意,它们可以基于 ID 的范围。对行列表和您收到的字典执行此操作,然后使用上面的代码一次处理每个 list/dict 相同 ID 的文件对。
不过,如果您必须保留接收词典的顺序,则此方法将更难实施。
lst
列表的一些预处理可能会有很大帮助。例如。将该字典列表转换为字典,其中 id
将是一个键。
准确的把lst
改成这样的结构:
lst = {
'1456': 'xxx',
'24234': 'yyy',
'3222': 'zzz',
...
}
然后当尝试检查 example_dict
中的 data
属性时,只需直接访问 lst
中的 id
键,如下所示:
if example_dict['data'] is None:
example_dict['data'] = lst.get(example_dict['id'])
它应该将时间复杂度从二次复杂度 (n*n) 降低到线性复杂度 (n)。
尝试从 lst
创建散列 table(在 Python 中 dict
)以加速基于 'id' 的查找:
lst = [
{'data': 'xxx', 'id': 1456},
{'data': 'yyy', 'id': 24234},
{'data': 'zzz', 'id': 3222},
{'data': 'foo', 'id': 1789},
]
example_dict = {'key': 'x', 'key2': 'y', 'id': 1456, 'data': None}
dct ={row['id'] : row for row in lst}
if example_dict['data'] is None:
example_dict['data'] = dct[example_dict['id']]['data']
print(example_dict)
示例输出:
{'key': 'x', 'key2': 'y', 'id': 1456, 'data': 'xxx'}
我有一个巨大的(大约 350k 个元素)字典列表:
lst = [
{'data': 'xxx', 'id': 1456},
{'data': 'yyy', 'id': 24234},
{'data': 'zzz', 'id': 3222},
{'data': 'foo', 'id': 1789},
]
另一方面,我收到了一个又一个缺失值的字典(大约 550k)(不是每个字典都缺失这个值),我需要更新它们:
example_dict = {'key': 'x', 'key2': 'y', 'id': 1456, 'data': None}
收件人:
example_dict = {'key': 'x', 'key2': 'y', 'id': 1456, 'data': 'xxx'}
我需要获取每个字典并在列表中搜索以匹配 'id' 并更新 'data'。这样做需要很长时间才能处理:
if example_dict['data'] is None:
for row in lst:
if row['id'] == example_dict['id']:
example_dict['data'] = row['data']
有没有办法构建一个结构化的分块数据,例如10k 值并告诉传入的字典在哪个块中搜索 'id'?或者任何其他优化方法?感谢任何帮助,保重。
使用字典而不是线性搜索列表。
第一个重要的优化是通过 lst
删除线性搜索,方法是构建一个索引为 id 并指向行
例如,如果您有足够的 RAM 来保存内存中的所有行,这将比您的代码快很多:
row_dict = {row['id']: row for row in lst}
if example_dict['data'] is None:
if example_dict['id'] in row_dict:
example_dict['data'] = row_dict[example_dict['id']]['data']
无论您是按 10k 块处理行还是一次性处理所有行,此改进都与您相关,因为字典查找时间是恒定的,而不是 lst
的线性大小。
制作您自己的分块过程
接下来你问“有没有办法构建一个结构化的分块数据......”。是的,一点没错。如果数据太大而无法放入内存,请编写一个 first pass 函数,将基于 id 的输入分成几个临时文件。如果顺序不相关,它们可以基于 ID 的最后两位数字,或者如果您愿意,它们可以基于 ID 的范围。对行列表和您收到的字典执行此操作,然后使用上面的代码一次处理每个 list/dict 相同 ID 的文件对。
不过,如果您必须保留接收词典的顺序,则此方法将更难实施。
lst
列表的一些预处理可能会有很大帮助。例如。将该字典列表转换为字典,其中 id
将是一个键。
准确的把lst
改成这样的结构:
lst = {
'1456': 'xxx',
'24234': 'yyy',
'3222': 'zzz',
...
}
然后当尝试检查 example_dict
中的 data
属性时,只需直接访问 lst
中的 id
键,如下所示:
if example_dict['data'] is None:
example_dict['data'] = lst.get(example_dict['id'])
它应该将时间复杂度从二次复杂度 (n*n) 降低到线性复杂度 (n)。
尝试从 lst
创建散列 table(在 Python 中 dict
)以加速基于 'id' 的查找:
lst = [
{'data': 'xxx', 'id': 1456},
{'data': 'yyy', 'id': 24234},
{'data': 'zzz', 'id': 3222},
{'data': 'foo', 'id': 1789},
]
example_dict = {'key': 'x', 'key2': 'y', 'id': 1456, 'data': None}
dct ={row['id'] : row for row in lst}
if example_dict['data'] is None:
example_dict['data'] = dct[example_dict['id']]['data']
print(example_dict)
示例输出:
{'key': 'x', 'key2': 'y', 'id': 1456, 'data': 'xxx'}