针对缺失项目的主列表的C#扫描列表

时间:2018-01-08 18:19:43

标签: c# list compare

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

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

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

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

所以在实践中它们应该是相同的,但是为了测试错误,我想比较tablesList和masterList,以确保所有需要的表都在那里。作为此过程的副本,如果masterList上没有任何额外的表,我也会撤消搜索。

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

我正在使用带有c#.net Core 2.0的Visual Studio 2017。

这是我到目前为止所做的尝试:

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

但有了这个,我收到了错误:

  

无法从IEnumerable转换为字符串

6 个答案:

答案 0 :(得分:2)

你在寻找类似的东西;

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

您可以使用.Except() IEnumerable set operations之一来捕捉差异:

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

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

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");
} 

答案 3 :(得分:1)

要查找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期望收集类型的单个项目,在这种情况下是{{1} }。您可以使用string代替,但我认为更好地使用所有内容就是我上面写的内容。

答案 4 :(得分:1)

我认为最好使用Except()如下

var MasterList =  new List<string> { "business", "customer", "location", "employee"};
var ChildList = new List<String> {  "customer", "location", "employee" };

var filter = MasterList.Except(ChildList);

这将是那些不在ChildList中的值。您也可以反过来。

答案 5 :(得分:-1)

您的代码目前正在尝试将IEnumerable添加到List。

如果你想添加所有的匹配,你应该改为AddRange。

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)));