【发布时间】:2016-06-30 10:16:27
【问题描述】:
我需要逐行比较 2 个 csv(大文件)并将不同的行写入单独的文件中。 一个文件中的行可以出现在第二个文件中的任何位置。我需要比较整行。 有什么指点吗?
【问题讨论】:
-
哇,这太宽泛了。但如果你想有一个体面的表现,我认为你需要读取内存中的整个 2 个文件来搜索重复项。如果行中的字段顺序相同,则可以使用 2
List<string>
我需要逐行比较 2 个 csv(大文件)并将不同的行写入单独的文件中。 一个文件中的行可以出现在第二个文件中的任何位置。我需要比较整行。 有什么指点吗?
【问题讨论】:
List<string>
一种常见的方法是计算一个文件中每一行的哈希码(最好是较小的那个)。然后将整个文件放入哈希表中。这将是较小文件的索引。
之后,浏览较大的文件。对于每一行计算其哈希值。然后查看索引。如果那里没有这样的哈希码,那么这一行就是区别。否则,如果存在这样的哈希码(可能不止一行会有相同的哈希),则将源行与哈希表中的所有冲突行进行整体比较,看看是否有重复。
现在,如果没有重复,则源文件中的行再次唯一并将其推送到输出。
否则,如果存在重复项,您可能希望从哈希表中删除该重复项并跳过输入行。这意味着两个文件中的两行已被检测为相等并将相互取消。
当您浏览完较大的文件后,您需要决定如何处理散列表中的剩余行。您可能还希望将它们全部推送到输出,因为这些行在其他文件中不存在。
现在我将尝试概述伪代码:
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)) 内存。
【讨论】:
又快又脏:
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();
}
【讨论】: