我有一个处理 csv 文件的程序。 CSV的内容如下
lines = [
[id_A, val1, val2, ..., valn],
[id_A, val1, val2, ..., valn],
[id_B, val1, val2, ..., valn],
[id_B, val1, val2, ..., valn],
[id_B, val1, val2, ..., valn],
[id_B, val1, val2, ..., valn],
[id_C, val1, val2, ..., valn],
[id_C, val1, val2, ..., valn],
]
我正在构建一个看起来像的字典
my_dict = {
'id_A': ['many', 'values'],
'id_B': ['many', ''more', 'values']
'id_C': ['some', 'other', 'values']}
我目前的实现看起来像
for line in lines:
log_id = line[0]
if log_id not in my_dict.keys():
datablock = lines[1:]
my_dict[log_id] = datablock
else:
my_dict[log_id].append(lines[1:])
csv 中有将近一百万行,一旦字典中有几千个条目,程序就会开始显着变慢。我一直在用一些打印语句调试它,瓶颈似乎在 if log_id not in my_dict.keys(): 行
我尝试使用单独的 list 来跟踪字典中已有的 ID,但这似乎没有帮助。
在这里使用 set 是否可行,或者该选项是否可行,因为它会更改每个循环并需要重建?
请您参考如下方法:
您每次都在创建所有键的列表。删除 dict.keys()打电话,它会减慢你的速度,但不需要:
if log_id not in my_dict:
字典直接支持成员资格测试,并且在 O(1) 时间内完成。 dict.keys() 返回一个新列表,但是,对列表的成员资格测试效率不高(需要 O(N) 时间)。因此,对于每个成员资格测试,您的代码将遍历所有 键以生成一个新的列表对象,然后再次遍历该列表以找到匹配项。
您可以使用 dict.setdefault() 稍微简化您的代码:
for line in lines:
log_id = line[0]
my_dict.setdefault(log_id, []).append(lines[1:])
dict.setdefault() 返回与给定键关联的值,如果缺少键,则使用第二个参数作为默认值(将键和值添加到字典中)。
或者,使用 collections.defaultdict() object而不是你的普通字典:
from collections import defaultdict
mydict = defaultdict(list)
for line in lines:
log_id = line[0]
my_dict[log_id].append(lines[1:])
defaultdict 是一个简单的 dict 子类,每当缺少一个键时,它都会调用配置的工厂;这里 list() 会在您尝试访问一个键时被调用,为丢失的键创建一个新值。
