【问题标题】:Optimise the removal of duplicate lines from a large file优化删除大文件中的重复行
【发布时间】:2014-11-22 12:17:16
【问题描述】:

如何优化此代码。我想从文件中删除重复的行,但认为如果效率低下使用该集合,并且会限制我可以解析的文件的大小。

file = open("sample.txt")

output = []
alreadyseen = set()    

while True:
    lines = file.readlines(100000)
    if not lines:
        break
    for line in lines:
        pass # do something
        if line not in alreadyseen:
            output.append(line)
            alreadyseen.add(line)
    print(output)   

【问题讨论】:

  • 文件有多大?二叉搜索树(它会给你 Log N 查找)怎么样?或者,如果行已排序,您可以迭代并只记住前一行...?
  • 如果它都适合内存,那么您在这里所拥有的技术可能是最佳的。如果您对一种即使不适合也有效的方法感兴趣,请直说。
  • 你关心行的顺序吗?
  • @erewok 一个集合是基于散列的,给出 O(1) 查找与 O(log n) 的树。
  • 如果文件适合内存,那么您的方法似乎没问题。如果没有,那么您可以查看这个问题:stackoverflow.com/questions/22623472/…

标签: python


【解决方案1】:

您的算法可能是最快的方法,但正如您所指出的,它会受到内存中可以容纳的行数的限制。有一些技术可以缓解这个问题并允许您处理更大的文件。

第一种是一次只能读写一行。由于您正在单独处理它们,因此无需一次读取 100000 个块,当然也没有理由将所有唯一结果保存在单个字符串中。一次读取和写入一行以最大程度地减少浪费。

第二个是用加密散列代替更长的字符串。无论行本身有多长,散列都是固定大小。如果您担心两个字符串产生相同散列的可能性,请不要担心 - 如果散列足够大,两个字符串产生相同散列的概率低于允许两个不同字符串生成的 RAM 故障的概率比较相等,即使考虑到birthday paradox

结合这两种方法看起来像这样:

import hashlib

sha256 = hashlib.sha256()
alreadyseen = set()
with open("sample.txt") as file:
    for line in file:
        pass # do something
        key = line if len(line) < 32 else sha256(line)
        if key not in alreadyseen:
            alreadyseen.add(key)
            print(line)

【讨论】:

    【解决方案2】:

    写入临时文件以避免存储列表中的所有行,然后重新打开这两个文件并使用 file2 的内容更新 file1

    alreadyseen = set()
    with open(file_1) as f1, open(file_2, "w") as f2:
        while True:
            lines = f1.readlines(100000)
            if not lines:
                break
            for line in lines:
                pass # do something
                if line not in alreadyseen:
                    f2.write(line)
                    alreadyseen.add(line)
    
    with open(file1, "w") as f1, open(file_2) as f2:
        for line in f2:
            f1.write(line)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-22
      • 2012-05-20
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 2022-10-29
      • 2023-01-08
      相关资源
      最近更新 更多