【问题标题】:How to search lines on text file in another text file如何在另一个文本文件中的文本文件上搜索行
【发布时间】:2017-06-10 04:47:21
【问题描述】:

我有 2 个文本文件,我想读取这些文件并确定 file1 中的任何行是否存在于 file2 中。

file1 中的每一行都包含 file2 中的信息的子集(file2 中的每一行都比 file1 更完整)。例如,file1 的行有列 (x,y,z),file2 的行有列(x,y,z,w)。

我想读取 file1 并且对于 file2 中也存在的任何 file1 行,我想保存 file2(x,y,z,w) 的那一行

我写了这段代码,但这没有给我任何答案:

var f1Lines = File.ReadAllLines(@"D:\test1.txt");
var f2LineInf1 = File.ReadLines(@"D:\test2.txt")
    .Where(line => f1Lines.Contains(line))
    .Select(line => line).ToList();

File.WriteAllLines(@"D:\result.txt", f2LineInf1);

我的文件很大(600 万条记录),我希望在最短的时间内得到结果。

一行文字1:

memberID        productID   Date            Rating  
A1004AX2J2HXGL  B0007RT9LC  May 30, 2005    3   

一行text2有上面的列+标题和正文。

【问题讨论】:

  • 速度是相对的,超过 1200 万行的平面文件几乎不会“很快”
  • @AustinFrench 好的。我的第一个问题是这段代码没有给我任何答案。
  • Where 无法给您答案,因为 text2 中的 line 有更多文字。你应该做一个字符串比较。你能从每个文件中发布一些示例文本吗?
  • 根据您的问题陈述,test1.txt 中的行包含 test2.txt 中的行的子集。如果是这样,那么f1Lines.Contains(line) 的声明永远不会是真的

标签: c# text-files


【解决方案1】:

您编写的代码正在检查f1Lines 中的任何行是否以f2LineInf1 中的当前行开头。因为我们知道第一个文件中的每一行都包含第二个文件中的行的子集,所以这永远不会是真的。

我们真正想做的是,对于第二个文件中的每一行,看看第一个文件中是否有任何行与第二个文件行的开头匹配。

这可以通过以下方式完成:

var f1Lines = File.ReadAllLines(@"f:\public\temp\temp1.txt");
var f2LineInf1 = File.ReadLines(@"f:\public\temp\temp2.txt")
    .Where(line => f1Lines.Any(line.StartsWith));

File.WriteAllLines(@"f:\public\temp\result.txt", f2LineInf1);

【讨论】:

  • 我只想要 temp2 中存在于 temp1 中的行。您的代码在 temp1 中存在的其他 temp2 行中,返回 temp1 中不存在的 temp2 行。我不要它
  • 此代码将只为您提供 temp2 中以 temp1 中的行开头的行。这就是f1Lines.Any(line.StartsWith) 的含义:如果它以f1Lines 中的任何行开头,则返回此temp2 行。你说 “它返回 temp1 中不存在的 temp2 行”。请查看其中的一行,并验证 temp1 中没有与行首匹配的行,或者提供两个文件的小示例,这些文件重现了您在使用此代码时看到的错误。是否有可能在您的 temp1 中有一些空白行正在匹配?
【解决方案2】:

另一个答案完全正确并且应该被接受,但这是另一种使用较少 LINQ 的方式。

var f1Lines = File.ReadAllLines(@"D:\test1.txt").ToList();
var f2Lines = File.ReadLines(@"D:\test2.txt").ToList();
var result = new List<string>();
foreach (var item in f1Lines)
{
    var found = f2Lines.Where((line) => line.Contains(item)).FirstOrDefault();
    if (found != null)
    {
        result.Add(found);
    }
}

File.WriteAllLines(@"D:\result.txt", result);

【讨论】:

  • 此代码适用于小型数据集。但是对于我的数据集,内存不足。有解决这个问题的办法吗?
【解决方案3】:

我建议使用HashSet&lt;string&gt;(不是List&lt;string&gt;string[])作为临时集合;像这样:

 // Hash set is a most efficient - O(1) - data stucture for Contains
 // When working with 1e6 records O(n)/O(1) choice does matter...
 HashSet<string> toFind = new HashSet<string>(File.ReadLines(@"D:\test1.txt"));

 File.WriteAllLines(@"D:\result.txt", File
   .ReadLines(@"D:\test2.txt") 
   .Where(line => toFind.Contains(line)));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多