[英]Remove items from one list if they contain strings from another list
如果项目包含另一个列表中的字符串,我正在寻找从一个列表中删除项目的最有效方法。
例如:
B 列表包含:
TomWentFishing
SueStayedHome
JohnGoesToSchool
JimPlaysTennis
一个列表包含:
GoesToSchool
SueStayed
C 列表应包含:
TomWentFishing
JimPlaysTennis
我已经使用了这段代码,但是由于列表非常大,它会占用很多时间:
static void Main(string[] args)
{
string[] b = File.ReadAllLines(@"C:\b.txt");
string[] a = File.ReadAllLines(@"C:\a.txt");
foreach (string firststring in b)
{
bool contains = false;
foreach (string secondstring in a)
{
if (firststring.ToLower().Contains(secondstring.ToLower()))
{
contains = true;
break;
}
}
if (contains == false)
{
File.AppendAllText(@"C:\c.txt", firststring + Environment.NewLine);
}
}
}
如果您可以将列表排序a
可以支持二进制(或更快)查找的内容,则可以显着加快速度。
不幸的是, Contains()
搜索使这具有挑战性。 但是我们仍然可以做一些事情:
b
加载到 RAM 中。 曾经。a
会更快,并尽可能多地支持对这个副本的查找。b
转换为小写一次,而不是对a
中的每一行再次转换。static void Main(string[] args)
{
var b = File.ReadLines(@"C:\b.txt");
var a = File.ReadLines(@"C:\a.txt").Select(line => line.ToLower()).ToList();
var result = b.Where(bline => {
var lowered = bline.ToLower();
return !a.Any(aline => lowered.Contains(aline));
});
File.AppendAllLines(@"C:\c.txt", result);
}
在这里,您有一个非常有效的基于哈希集的实现,它是线性时间复杂度 O(n)。 这避免了您为 b.txt 文件中的每一行迭代 a.txt 文件的所有行,这会导致二次时间复杂度 O(n^2)。
如果包含所有 a.txt 文件行的哈希集适合内存,则此方法很好。 如果它不适合内存,那么您需要使用 RocksDb 之类的东西。
首先你有这个扩展方法:
public static class EnumerableStringExtensions
{
public static IEnumerable<string> Minus(
this IEnumerable<string> minuend,
IEnumerable<string> subtrahend,
StringComparison comparisonType)
{
var subtrahendSet = new HashSet<string>(subtrahend, StringComparer.FromComparison(comparisonType));
return minuend.Where(x => subtrahendSet.Contains(x) == false);
}
}
你可以像这样使用它:
public class Program
{
public static IEnumerable<string> EnumerateLines(string filePath)
{
using (var reader = File.OpenText(filePath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
static void Main(string[] args)
{
var minuend = EnumerateLines("b.txt");
var sustraend = EnumerateLines("a.txt");
var difference = minuend.Minus(sustraend, StringComparison.OrdinalIgnoreCase);
File.WriteAllLines("difference.txt", difference);
}
}
请注意,使用此实现,您不需要一次将 b.txt 文件中的所有行保存在内存中。 但是您需要一个包含 a.txt 中所有行的哈希集
如果问题是由于文件大小而导致内存使用率高,那么您已经读取了一个文件,但对于另一个文件而不是直接读取内存中的整个文件,您可以使用 FileInputStream 和 BufferedReader 逐行读取。 这将减少一些内存使用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.