按列和值比较两个 csv 文件并显示不同值的行号 [关闭]

Posted

技术标签:

【中文标题】按列和值比较两个 csv 文件并显示不同值的行号 [关闭]【英文标题】:Comparing two csv files by column and value and displaying line numbers of differing values [closed] 【发布时间】:2016-07-06 11:47:40 【问题描述】:

我正在为两个包含列和对应值的 csv 文件做一个比较器 对于每个新行上的每一列。列在文件的第一行指定。之后的每一行都包含每一列的数据。

我正在尝试创建一个程序,该程序可以处理具有不同行号和列数的文件,并且还可以显示不同值的行号,然后创建一个显示行号的新文本文件,列文件 1 和文件 2 的名称和值。

应该根据一些标识符而不是逐行进行比较。 如果在列行中指定了某些列数据丢失,那么它可以显示数据丢失的列数。

例如: worker1.csv:

姓名;年龄;身高;性别; 鲍勃;21;190;男 约翰;35;182;男 玫瑰; 玛丽;20;175;女

worker2.csv

姓名;年龄;身高;性别 鲍勃;21;185;男 约翰;30;186;男 玛丽;

输出.csv

玛丽发现的不同之处: 文件 2,第 3 行,缺少三个值 在 Bob 中发现的差异: 文件 1,行号 1,高度:190 文件 2,行号 1,高度:185 在 John 中发现的差异: 文件 1,第 2 行,年龄:35,身高:182 文件 2,第 3 行,年龄:30,身高:186

我应该怎么做?我确实在两个文件行上都查看了 LINQ 的“除外”,但我怎样才能获得行号?

【问题讨论】:

我会将 csv 数据读入 DataTables。网上有很多信息可以比较两个数据表。在以下帖子中查看我的导入代码:***.com/questions/30129406/… 欢迎来到堆栈溢出 :-) 到目前为止你尝试了什么?请向我们展示您的代码。请看How to Ask 谢谢 :) 原来这比我最初的复杂。我已经尝试了一个混乱的解决方案,将每一行转换为具有相应键和值的字典。所以 1 个文件基本上形成了一个字典列表,然后我将其与另一行的字典进行比较。虽然我让它以某种方式工作,但它非常复杂,如果可比较的文件具有不同的行数,或者另一个文件的行具有不同数量的值,它很容易中断。到目前为止,我大部分时间都在放弃我的解决方案:D output.csv最后一行应该是文件2,行号2,年龄:30,身高:186 【参考方案1】:

这比它第一次出现时要复杂一些。但如果你一步一步地接近它,它是可行的。

我将假设您有足够的内存来将文件的一条记录加载到字典中。如果您的文件非常大,事情就会变得复杂得多。

您要做的第一件事是将其中一个文件加载到由 ID 索引的字典中。在我的示例中,我假设 ID 是名称。每条记录都将记录在一个FileLine 实例中:

class FileLine

    public int LineNumber;
    public string Name;
    public int Age;
    public int Height;
    public string Gender;

还有你的字典:

Dictionary<string, FileLine> File1Lines = new Dictionary<string, FileLine>();

现在,将文件读入该字典:

int lineNumber = 0;
foreach (var line in File.ReadLines("worker1.csv")

    // split the line and assign the fields.
    // End up with name, age, height, and gender variables.
    ++lineNumber;
    var theLine = new FileLine(
        LineNumber = lineNumber,
        Name = name,
        Age = age,
        Height = height,
        Gender = gender);
    File1Lines.Add(theLine.Name, theLine);

现在,您可以阅读第二个文件,在字典中查找该项目,并报告任何差异:

lineNumber = 0;
foreach (var line in File.ReadLines("worker2.csv"))

    // split the line and create a FileLine instance.
    // we'll call it line2
    // Then, look to see if that line is in the File1Lines dictionary.
    FileLine line1;
    if (!File1Lines.TryGetValue(line2.Name, out line1))
    
        // the line didn't exist in the first file
    
    else
    
        // Now compare individual fields
        if (line2.Age != line1.Age)
        
            // report that fields are different
        
        // Do the same with other fields
    

现在,如果您想跟踪第一个文件中但不在第二个文件中的行,则创建一个HashSet&lt;string&gt;,并且每当您在第二个文件中找到记录时,将名称添加到散列放。完成第二个文件后,您可以将哈希集与字典中的键进行比较。因此,如果您的哈希集称为FoundRecords,那么您将拥有:

var recordsNotFound = File1Lines.Keys.Except(FoundRecords);
foreach (var name in recordsNotFound)

    // look up item in the dictionary to report not found

【讨论】:

谢谢!我必须说我忘了提及数据中列的实际数量:实际上有超过 50 个可能的列,尽管行的数量不应该那么大。这么多列仍然可以使用此解决方案吗?还是应该忘记按列报告差异? @Makezu:有那么多列仍然是可能的。您可以选择像我一样创建一个类,每列有一个属性,或者您可以在类中放置一个字典来保存名称和值。由你决定。但列数不应影响此解决方案的有效性。【参考方案2】:

从两个foreach-loop中可以看出区别,或者使用for-loop也可以:

string[] content1 = File.ReadAllLines(@"worker1.csv");
string[] content2 = File.ReadAllLines(@"worker2.csv");
for(int i = 0; i < content1.Length; i++)

  // check here every line, i is your line number

for(int i = 0; i < content2.Length; i++)

  // check here every line, i is your line number

【讨论】:

以上是关于按列和值比较两个 csv 文件并显示不同值的行号 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Python:用于比较 .csv 的标头和值、更新值的脚本

比较两个文本文档的不同,并显示第一出不同的行号列号

在 Python 3.x 中将基于特定列的列和值的两个 DataFrame 与 Pandas 合并

Groovy 比较两个带有未知节点名称和值的 json

如何使用分隔列和值的数组生成查询

列和行操作 Python Pandas