C# 根据主列表扫描列表以查找缺失项



我有一个主列表,其中包含我知道正确的数据库表的值:

masterList: List<string>(){ "business", "customer", "location", "employee", etc}

我查询了一个应该相同的新数据库。我的测试将告诉我我的团队为制作这个新数据库而制作的脚本中是否有任何错误。tablesList 应该是我的查询的返回:

tablesList: List<string>(){ "business", "customer", "location", "employee", etc}

所以在实践中它们应该是相同的,但为了测试错误,我想将 tablesList 与 masterList 进行比较,以确保所有需要的表都在那里。作为此过程的副本,我也在反转搜索,以防万一主列表中没有任何额外的表。

问:如何将列表与主列表进行比较,并返回不匹配的项目?

我正在使用Visual Studio 2017和c# .net Core 2.0。

这是我到目前为止一直在尝试的:

var errorsList = new List<string>();
tablesList = QuerySchemaForTables();
masterList = GrabMasterTableList();
foreach(var item in masterList)
errorsList.Add(tablesList.Where(x => x.Contains(item)));

但是有了这个,我得到了错误:

无法从 IEnumerable 转换为字符串

可以使用 LINQ 获取错误的两个方向。无需循环:

var missingInMasterList = tableList.Where(x => !masterList.Contains(x)).ToList();
var missingInTableList = masterList.Where(x => !tableList.Contains(x)).ToList();

你在寻找类似的东西吗?

var errorList = tableList.Where(x => !masterList.Contains(x));

您可以使用.Except()捕获差异,这是IEnumerable集合操作之一:

var missingTables = masterList.Except(tablesList);
var extraTables = tablesList.Except(masterList);

然后,要创建错误消息,您可以使用string.Join()将这些IEnumerables中的项目用逗号联接到单个字符串中:

var errorMessage = new StringBuilder();
if (missingTables.Any())
{
errorMessage.AppendLine("Missing Tables: " + string.Join(", ", missingTables));
}
if (extraTables.Any())
{
errorMessage.AppendLine("Extra Tables: " + string.Join(", ", extraTables));
}

然后,您可以通过检查errorMessage长度来确定是否遇到任何错误来输出结果:

if (errorMessage.Length > 0)
{
Console.WriteLine(errorMessage.ToString());
}
else
{
Console.WriteLine("No extra or missing tables detected");
} 

我认为更好的使用方式如下Except()

var MasterList =  new List<string> { "business", "customer", "location", "employee"};
var ChildList = new List<String> {  "customer", "location", "employee" };
var filter = MasterList.Except(ChildList);

这将值那些不在ChildList。反之亦然。

要查找tablesList中但不在masterList中的所有项目,请使用.Contains

var errorsList = tableList.Where(x => !masterList.Contains(x));

但我建议您使用HashSet<String>表示masterList,因此在其中搜索项目将在O(1)而不是O(n)

var masterCollection = new HashSet<String>(GrabMasterTableList());
var errorsList = tableList.Where(x => !masterCollection.Contains(x));

至于您发布的代码问题:

foreach(var item in masterList)
errorsList.Add(tablesList.Where(x => x.Contains(item))); // <-- error

正如错误所指出的那样,Linq 的.Where返回一个IEnumerable<T>,而.Add需要集合类型的单个项目,在本例中为单个string。你可以改用.AddRange,但我认为更好的用法是我上面写的。

您的代码当前正在尝试将 IEnumerable 添加到列表中。

如果要添加所有匹配项,则应改为添加范围。

https://msdn.microsoft.com/en-us/library/z883w3dc(v=vs.110).aspx

var errorsList = new List<string>();
tablesList = QuerySchemaForTables();
masterList = GrabMasterTableList();
foreach(var item in masterList)
errorsList.AddRange(tablesList.Where(x => x.Contains(item)));

最新更新