用于删除重复项的python脚本,需要24小时+循环遍历10 ^ 7条记录

时间:2014-06-26 13:48:13

标签: python optimization

输入t1
P95P,71655,LINC-JP,致病
P95P,71655,LINC-JP,致病
P71P,71655,LINC-JP,致病
P71P,71655,LINC-JP,致病

输出操作
P95P,71655,LINC-JP,致病
P71P,71655,LINC-JP,致病

mycode的

def dup():
    fi=open("op","a")
    l=[];final="";
    q=[];dic={};
    for i in open("t1"):
        k=i.split(",")
        q.append(k[1])
        q.append(k[0])
        if q in l:
            pass
        else:
            final= final + i.strip() + "\n"
            fi.write(str(i.strip()))
            fi.write("\n")
        l.append(q)
        q=[]
        #print i.strip()
    fi.close()
    return final.strip()    
d=dup()

在上面的输入行1,2和行3,4是重复的。因此,在输出中删除了这些重复项,输入文件中的条目大约为10 ^ 7。

为什么我的代码自24小时后运行以输入76Mb文件。它还没有完成整个输入文件的一次迭代。它适用于小文件。
任何人都可以指出这么长时间的原因。我如何优化我的程序?
日Thnx

4 个答案:

答案 0 :(得分:6)

您正在使用O(n 2 )算法,该算法对较大的文件进行缩放:

for i in open("t1"):  # linear pass of file takes O(n) time
    ...
    if q in l:  # linear pass of list l takes O(n) time
        ...
    ...

如果重复项始终彼此相邻,您应该考虑使用set(即使lset)或itertools.groupby。这些方法将是O(n)。

答案 1 :(得分:5)

如果您可以访问Unix系统,uniq是一个很好的实用程序,可以解决您的问题。

uniq input.txt output.txt

请参阅https://www.cs.duke.edu/csl/docs/unix_course/intro-89.html

我知道这是一个Python问题,但有时Python不是该任务的工具。 并且您始终可以在python脚本中嵌入系统调用。

答案 2 :(得分:2)

目前尚不清楚为什么要构建一个巨大的字符串(final)来保存与文件相同的内容,或dic的内容。就性能而言,如果x in yy而非sety,则可以更快地查找list。还有一个小问题;较短的变量名称不会提高性能,因此请使用好的名称。我建议:

def deduplicate(infile, outfile):
    seen = set()
    #final = []
    with open(outfile, "a") as out, open(infile) as in_:
        for line in in_:
            check = tuple(line.split(",")[:2])
            if check not in seen:
                #final.append(line.strip())
                out.write(line) # why 'strip' the '\n' then 'write' a new one?
                seen.add(check)
    #return "\n".join(final)

如果确实需要final,请将其列为最后一刻(请参阅注释掉的行) - 渐进式字符串连接意味着创建大量不必要的对象。

答案 3 :(得分:1)

有些事情你做得非常低效。最大的一点是您将l列为一个列表,因此行if q in l必须搜索列表中的所有内容,以便检查q是否与之匹配。如果你创建la set,则可以使用哈希计算和数组查找来完成成员资格检查,无论你添加多少集合都会花费相同的(小)时间(尽管它会导致{{ 1}}不按照它的写入顺序阅读。

您可以做的其他小加速包括:

  • 使用tupple l代替(k[1], k[0])的列表。
  • 您正在每个循环编写输出文件q。您的操作系统将尝试批量处理写入操作,但最后只需执行一次大写操作可能会更快。我不确定这一点,但试试吧。