【问题标题】:How to compare two large CSV files and get the difference file如何比较两个大型 CSV 文件并获取差异文件
【发布时间】:2016-06-30 10:16:27
【问题描述】:

我需要逐行比较 2 个 csv(大文件)并将不同的行写入单独的文件中。 一个文件中的行可以出现在第二个文件中的任何位置。我需要比较整行。 有什么指点吗?

【问题讨论】:

  • 哇,这太宽泛了。但如果你想有一个体面的表现,我认为你需要读取内存中的整个 2 个文件来搜索重复项。如果行中的字段顺序相同,则可以使用 2 List<string>

标签: c# file csv compare


【解决方案1】:

一种常见的方法是计算一个文件中每一行的哈希码(最好是较小的那个)。然后将整个文件放入哈希表中。这将是较小文件的索引。

之后,浏览较大的文件。对于每一行计算其哈希值。然后查看索引。如果那里没有这样的哈希码,那么这一行就是区别。否则,如果存在这样的哈希码(可能不止一行会有相同的哈希),则将源行与哈希表中的所有冲突行进行整体比较,看看是否有重复。

现在,如果没有重复,则源文件中的行再次唯一并将其推送到输出。

否则,如果存在重复项,您可能希望从哈希表中删除该重复项并跳过输入行。这意味着两个文件中的两行已被检测为相等并将相互取消。

当您浏览完较大的文件后,您需要决定如何处理散列表中的剩余行。您可能还希望将它们全部推送到输出,因为这些行在其他文件中不存在。

现在我将尝试概述伪代码:

dict = new dictionary<code, list<row>>

-- Indexing phase
foreach row in file1
    code = hash(row)
    if dict.contains(code) then
        dict[hash].add(row)
    else
        dict[hash] = new list(row)

-- Comparison phase
foreach row in file2
    code = hash(row)
    bool unique = true
    if dict.contains(code) then
        foreach indexedRow in dict[code]
            if indexedRow is the same as row then
                begin
                    unique = false
                    remove indexedRow from dict[code]
                end
    if unique then
        push row to output

-- Finalization phase
foreach row in dict
    push row to output

这个解决方案的最大优点是它的运行时间复杂度是 O(M + N),其中 M 和 N 是每个文件中的行数。它的缺点是索引需要 O(min(M, N)) 内存。

【讨论】:

    【解决方案2】:

    又快又脏:

    private void DoSomething()
    {
      var lines1 = File.ReadAllLines(@"file1.csv");
      var lines2 = File.ReadAllLines(@"file2.csv");
    
      var diff1From2 = FindDifferences(lines1, lines2);
      var diff2From1 = FindDifferences(lines2, lines1);
    
      var diffs = new List<string>(diff1From2);
      diffs.AddRange(diff2From1);
      File.WriteAllLines(@"file3.csv", diffs);
    }
    
    private static string[] FindDifferences(string[] linesFirst, string[] linesSecond)
    {
      return (from line1 in linesFirst
        let isLineEqual = linesSecond.Any(line2 => line1 == line2)
        where isLineEqual == false
        select line1).ToArray();
    }
    

    【讨论】:

    • 此解决方案的复杂度为 O(N*M),在大型 CSV 文件中效率非常低。另一个答案中概述的解决方案的复杂度为 O(N + M)。
    猜你喜欢
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多