我有一个处理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
,或者是那个选项,因为它改变了每个循环并且需要重建吗?
答案 0 :(得分:12)
您每次都会创建所有键的列表。移除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()
被调用,以便在您尝试访问密钥时为缺失密钥创建新值。