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

时间:2014-06-19 15:56:09

标签: 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],
 ]

我正在构建一个类似于

的字典
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,或者是那个选项,因为它改变了每个循环并且需要重建吗?

1 个答案:

答案 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()被调用,以便在您尝试访问密钥时为缺失密钥创建新值。