我有> 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
答案 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