Python - 迭代字典键时的性能

标签 python loops dictionary frequency large-files

我有一个相对较大的文本文件(大约 700 万行),我想对其运行特定的逻辑,我将在下面尝试解释:

A1KEY1
A2KEY1
B1KEY2
C1KEY3
D1KEY3
E1KEY4

我想统计按键出现的频率,然后将频率为1的输出到一个文本文件中,将频率为2的输出到另一个文本文件中,将频率高于2的输出到另一个文本文件中。

这是我目前为止的代码,但它遍历字典的速度非常慢,而且越进展越慢。

def filetoliststrip(file):
    file_in = str(file)
    lines = list(open(file_in, 'r'))
    content = [x.strip() for x in lines] 
    return content


dict_in = dict()    
seen = []


fileinlist = filetoliststrip(file_in)
out_file = open(file_ot, 'w')
out_file2 = open(file_ot2, 'w')
out_file3 = open(file_ot3, 'w')

counter = 0

for line in fileinlist:
    counter += 1
    keyf = line[10:69]
    print("Loading line " + str(counter) + " : " + str(line))
if keyf not in dict_in.keys():
    dict_in[keyf] = []
    dict_in[keyf].append(1)
    dict_in[keyf].append(line)
else:
    dict_in[keyf][0] += 1
    dict_in[keyf].append(line)


for j in dict_in.keys():
    print("Processing key: " + str(j))
    #print(dict_in[j])
    if dict_in[j][0] < 2:
        out_file.write(str(dict_in[j][1]))
    elif dict_in[j][0] == 2:
        for line_in in dict_in[j][1:]:
            out_file2.write(str(line_in) + "\n")
    elif dict_in[j][0] > 2:
        for line_in in dict_in[j][1:]:
            out_file3.write(str(line_in) + "\n")


out_file.close()
out_file2.close()
out_file3.close()

我在配备 8GB Ram 的 Windows PC i7 上运行它,这应该不会花费数小时来执行。这是我将文件读入列表的方式的问题吗?我应该使用不同的方法吗?提前致谢。

最佳答案

你有多个点会减慢你的代码 - 没有必要将整个文件加载到内存中只是为了再次迭代它,也没有必要在每次你想要查找时都获取一个键列表( if key not in dict_in: ... 就足够了,而且速度非常快),你不需要保留行数,因为你可以事后检查行的长度......命名但有几个。

我会将您的代码完全重组为:

import collections

dict_in = collections.defaultdict(list)  # save some time with a dictionary factory
with open(file_in, "r") as f:  # open the file_in for reading
    for line in file_in:  # read the file line by line
        key = line.strip()[10:69]  # assuming this is how you get your key
        dict_in[key].append(line)  # add the line as an element of the found key
# now that we have the lines in their own key brackets, lets write them based on frequency
with open(file_ot, "w") as f1, open(file_ot2, "w") as f2, open(file_ot3, "w") as f3:
    selector = {1: f1, 2: f2}  # make our life easier with a quick length-based lookup
    for values in dict_in.values():  # use dict_in.itervalues() on Python 2.x
        selector.get(len(values), f3).writelines(values)  # write the collected lines

而且您很难获得比这更高效的方法,至少在 Python 中是这样。

请记住,在 Python 3.7(或 CPython 3.6)之前,这不能保证输出中行的顺序。但是,键本身内的顺序将被保留。如果您需要保持上述 Python 版本之前的行顺序,您必须保留一个单独的键顺序列表并迭代它以按顺序选取 dict_in 值。

关于Python - 迭代字典键时的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50364221/

相关文章:

c - 循环平铺优化

java - 榛卡斯特 map : remove entries owned by the node that goes down

sorting - 如何防止 map 排序?

python - Python中的关键字提取

python - 在我的 virtualenv 中,我需要对所有命令使用 sudo

python - 是否可以 os.walk 2 个不同的文件目录并在遍历时将它们相互比较

Javascript在循环中的特定数量的字母后添加字母

java - 我该如何解决这个简单的范围界定错误?

python - 比较Python中的两个字典

python - 这个 Django 模板标签是什么?