Python加速:检查列表中的值是否为

Bri*_*ach 1 python optimization

我有一个处理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],
 ]
Run Code Online (Sandbox Code Playgroud)

我正在建立一个看起来像的字典

my_dict = {
 'id_A': ['many', 'values'],
 'id_B': ['many', ''more', 'values']
 'id_C': ['some', 'other', 'values']}
Run Code Online (Sandbox Code Playgroud)

我目前的实现看起来像

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:])
Run Code Online (Sandbox Code Playgroud)

在csv中接近一百万行,一旦字典中有几千个条目,程序开始显着减慢.我一直在打印报表的飞溅调试它,和瓶颈似乎是这里的if log_id not in my_dict.keys():

我尝试使用单独的字符list来跟踪字典中已经存在的ID,但这似乎没有帮助.

可以set在这里使用,或者是那个选项,因为它改变每个循环并需要重建?

Mar*_*ers 12

每次都在创建所有键的列表.移除dict.keys()呼叫,它会减慢您的速度,但不需要:

if log_id not in my_dict:
Run Code Online (Sandbox Code Playgroud)

字典直接支持成员资格测试,并在O(1)时间内完成.但是,dict.keys()返回一个新列表,并且列表上的成员资格测试效率不高(需要O(N)时间).因此,对于每个成员资格测试,您的代码将循环遍历所有键以生成新的列表对象,然后再次遍历该列表以查找匹配项.

您可以使用dict.setdefault()以下方法简化代码:

for line in lines:
    log_id = line[0]
    my_dict.setdefault(log_id, []).append(lines[1:])
Run Code Online (Sandbox Code Playgroud)

dict.setdefault() 返回与给定键关联的值,如果缺少键,则使用第二个参数作为默认值(将键和值添加到字典中).

或者,使用collections.defaultdict()对象而不是普通字典:

from collections import defaultdict

mydict = defaultdict(list)

for line in lines:
    log_id = line[0]
    my_dict[log_id].append(lines[1:])
Run Code Online (Sandbox Code Playgroud)

A defaultdict是一个简单的dict子类,每次缺少一个键时都会调用配置的工厂; 这里list()被调用为您尝试访问密钥时创建缺失密钥的新值.