提高列表中匹配字符串的速度

时间:2018-04-19 08:49:45

标签: c# lambda matching

我有> 20MB的文本文件,其中一些行在某些位置包含*。因此应从该文件中删除与包含*的位置匹配的位置(例如700670 *应该导致删除所有位置70067000000至70067099999)。首先,我列出了删除代码的位置:

Parallel.ForEach(List, (pos) =>
{ if (pos.IndexOf("*") != -1)
 { var lineWithStar = pos.Substring(0, pos.IndexOf("*"));
    var result = from single in List 
    where single.Substring(0, lineWithStar.Length) == lineWithStar
    select single;
    listWithPositionsToDel.AddRange(result.Skip(1).ToList());
  }
});

获得结果需要很长时间。

我需要从输入文件中删除“123456”行 - 所有匹配123 *。

123 *

123456

1245

E.g。 结果应如下所示: 700204 * 700205100614136 * 700205100662305 * 7002051006623443904 700205100667271 * 700205120015472 * 来源是: 700204 * 700205100614136 * 7002041232323234332 700205100662305 * 7002051006141362332 7002051006623443904 700205100667271 * 700205120015472

2 个答案:

答案 0 :(得分:1)

你有嵌套循环,这会影响你的表现。此外,您还要进行大量额外的字符串和列表分配。

我会这样做:浏览文件一次,找到你需要删除的所有模式。然后迭代另一次,每一行立即决定是否需要删除该行或保留它。然后,您可以使用需要保留或直接写入新文件的行创建新列表,或者只是在单独的集合中添加要删除的项目。像这样的东西

var linePatternsToRemove = new List<String>();
var resultList = new ConcurrentBag<String>();
foreach (var line in List)
{
    var asteriskIndex = line.IndexOf("*");
    if (asteriskIndex != -1)
    {
        linePatternsToRemove.Add(line.Substring(0, asteriskIndex));
    }
}

Parallel.ForEach(List, currentLine =>
{
    Boolean needDeleteLine = false;
    foreach (var pattern in linePatternsToRemove)
    {
        if (currentLine.StartsWith(pattern))
        {
            // If line starts with pattern like "700204" it may be the pattern line itself "700204*" and we don't need to delete it
            // or it can be regular line and we like "70020412" and we need to delete it.
            if (currentLine.Length > pattern.Length && currentLine[pattern.Length] != '*')
            {
                needDeleteLine = true;
                break;
            }
        }
    }
    if (!needDeleteLine)
        resultList.Add(currentLine);
});

更新:可能你不会需要Parallel.Foreach和简单的for循环工作得足够快。但是如果你需要并行,你应该考虑线程安全的收集结果。

Update2:对代码进行了更改以反映新信息。请注意,使用并行循环时,输出结果集合将出现故障。此外,性能将在很大程度上取决于文件中的模式数量。如果你有大量的模式,需要更复杂的解决方案来测试每一行与许多不同的模式。在这种情况下,可能使用树木对你来说是个不错的选择。

答案 1 :(得分:0)

我需要删除行&#34; 123456&#34;来自输入文件 - 匹配123 *的所有内容。

123*

123456

1245