如何比较(比较)两个顺序无关紧要的大型 CSV 文件

问题描述 投票:0回答:2

我正在努力比较(比较)2 个大型 CSV 文件。

  • 行的顺序并不重要
  • 我不需要打印差异或任何内容,只需打印 True 或 False。

例如:

文件1

a,b,c,d
e,f,g,h
i,j,k,l

文件2

a,b,c,d
i,j,k,l
e,f,g,h

上面应该是可以通过比较的,虽然行的顺序不一样,但是内容是一样的。

如果内容不同、列值不匹配、或者某一行存在于另一行中,等等,则比较应该失败。

我遇到的最大问题是文件非常大,并且没有可排序的键列。文件有 14 到 3000 万行,大约 10 到 15 列。未排序的原始数据转储约为 1GB 的 csv 文件。

现在我正在尝试使用下面的代码对文件进行排序和“比较”。问题是“排序”并不总是有效。对于较小的文件和较少的行,排序和比较可以工作,但它似乎不适用于非常大的文件。

此外,排序也会显着增加操作时间;理想情况下,我想避免排序,只是比较忽略排序顺序,但我不知道该怎么做。

filecmm、difflib 和我尝试过的其他一些功能都需要预先排序的文件。

我现在正在执行 Python 合并排序,但正如我所说,排序不一定适用于大量行,我希望有更好的比较方法。

这是Python的归并排序函数:

def batch_sort(self, input, output, key=None, buffer_size=32000, tempdirs=None):
                if isinstance(tempdirs, str):
                        tempdirs = tempdirs.split(",")

                if tempdirs is None:
                        tempdirs = []
                if not tempdirs:
                        tempdirs.append(gettempdir())

                chunks = []
                try:
                        with open(input,'rb',64*1024) as input_file:
                                input_iterator = iter(input_file)
                                for tempdir in cycle(tempdirs):
                                        current_chunk = list(islice(input_iterator,buffer_size))
                                        if not current_chunk:
                                                break
                                        current_chunk.sort(key=key)
                                        output_chunk = open(os.path.join(tempdir,'%06i'%len(chunks)),'w+b',64*1024)
                                        chunks.append(output_chunk)
                                        output_chunk.writelines(current_chunk)
                                        output_chunk.flush()
                                        output_chunk.seek(0)
                        with open(output,'wb',64*1024) as output_file:
                                output_file.writelines(self.merge(key, *chunks))
                finally:
                        for chunk in chunks:
                                try:
                                        chunk.close()
                                        os.remove(chunk.name)
                                except Exception:
                                        pass

我可以调用batch_sort(),给它一个输入文件和输出文件、块的大小以及要使用的临时目录。

一旦我对两个文件执行batch_sort(),我就可以“diff file1 file2”。

以上适用于 25,000 到 75,000 行,但当我们谈论超过 1400 万行时则不适用。

python compare diff large-files
2个回答
1
投票

只需使用

set
并添加每一行。最后比较一下集合:

def compare(file1, file2):
    with open(file1) as fh1, open(file2) as fh2:
        left = {line for line in fh1}
        right = {line for line in fh2}

    return left == right

如果你真的很关心大小,你可以使用一个文件,而第二个文件中找不到第二行,你可以将其短路:

def compare(file1, file2):
    with open(file1) as fh:
        left = {line for line in fh}
    
    right = set()

    with open(file2) as fh:
        for line in fh:
            if line not in left:
                return False
        
            right.add(line)

    return left == right

0
投票

使用最低公分母算法不太可能起作用。 Big-Oh 表示法告诉您,读取、排序和比较这些操作至少需要 O(n),其中 n == 文件中的行数。

there is no key column to sort on
- 也许数据中没有自然键,但您应该能够为每一行生成一个哈希字符串并对其进行排序。如果您可以保证每行的哈希值都是唯一的,则不需要所有数据。然后你就可以对哈希列表进行操作了。

我看到的最大问题是要求两者同时存在于内存中。物理学说,当 X > Y 时,您无法将 X 放入 Y 容量的容器中。

© www.soinside.com 2019 - 2024. All rights reserved.