Python - 过滤/排序大文件的建议?

时间:2011-08-09 16:36:35

标签: python sorting filter

我有一个包含约2000万行(~1.5GB)的文件。每一行的形式如下:

entry_1 entry_2 entry_3 ......... entry_5

该文件包含重复项,但格式为:

entry_2 entry_1 entry_3 ......... entry_5

某些行的内容相同,但前两个元素通常(可能始终)切换。

有没有人对如何从这样大小的文件中删除此类重复项有任何建议?

感谢。

2 个答案:

答案 0 :(得分:5)

合适的解决方案取决于您拥有的约束以及运行此操作的频率。

如果这是一次性(或不经常)操作,并且如果内存使用不是一个大问题,那么这样就足够了:

visited = set() # use set for faster lookups
with open(out_filename, "w") as outfile:
    with open(in_filename, "r") as infile:
        for line in infile:
            x = line.split()
            k = (tuple(sorted(x[:2])), tuple(x[2:]))
            if k not in visited:
                outfile.write(line)
                visited.add(k)

内存使用情况取决于我们需要在visited中跟踪的唯一条目的数量。如果没有多少重复项,您最终将得到内存中的几乎所有数据。

如果内存使用成为问题,您可以分多个阶段执行此操作:

  1. 首先通过对每行中的前2个元素进行排序来预处理文件。
  2. 按行排序整个文件
  3. 现在可以直接删除重复项,因为重复的条目将一起显示。
  4. 第2步& 3可以合并,因为在执行排序时比较条目时可以简单地丢弃重复项。

    如果您不介意使用shell,可以使用sort -u yourfile完成第2步和第3步。

    请注意,这会更改文件中行的顺序(您提到的不是问题)。

    以显着降低内存使用率为代价,您可以使用基于文件的数据库来存储和查找访问过的条目(代替set())。

    您可以通过在内存中存储条目的哈希来加快速度,并且只在哈希匹配时查询数据库以确认条目是否确实相同。哈希可以像获取每个条目的第一个字符,或使用内置hash()函数一样简单,也可以选择existing hash algorithm。每种方法都是性能,散列大小和冲突频率之间的折衷。一个好的选择取决于您的数据和约束。

    这需要一些努力才能找到最佳解决方案。如果您需要经常执行此操作,则值得着手。

答案 1 :(得分:1)

separator = " "
aSet = set()
with open('myfile', 'rU') as infile:
    for line in infile:
        tempLine = line.split(separator)
        tempLine = tempLine[1:2] + tempLine[0:1] + tempLine[2:]
        tempLine = separator.join(tempLine)
        if line not in aSet and tempLine not in aSet:
            aSet.add(line)

现在,aSet包含唯一的行列表,无论是否已交换entry_1entry_2

编辑:如果可以交换所有条目并且该行仍被视为唯一,那么:

separator = " "
aSet = set()
with open('myfile', 'rU') as infile:
    for line in infile:
        aSet.add(frozenset(line.split(separator)))