C#Linq检查列表列表是否在列表列表内

时间:2019-03-01 19:12:36

标签: c# list linq

我有两个列表列表:
(1)变体和(2)选项

我需要查看变体内部是否存在所有选项(无论顺序如何)。

例如:在下面的代码中,我需要确保每个项目列表都出现在变体列表中-因此,无论顺序如何,列表“蓝色”,“红色”,“绿色”都必须出现在变体列表中

编辑(说明): “选项”内的所有列表都必须出现在“变量”中。如果其中之一失败,则布尔值必须返回false。

我设置了LINQ条件,但不确定为什么它不起作用。任何帮助将不胜感激。

 //TEST 1

    List<List<string>> variants = new List<List<string>>();
    variants.Add(new List<string> {"cars", "boats", "planes"});
    variants.Add(new List<string> {"money", "trees", "plants"});
    variants.Add(new List<string> {"green", "blue", "red" });
    variants.Add(new List<string> {"kid", "adult", "senior"});
    variants.Add(new List<string> {"tax", "insurance", "salary"});

    List<List<string>> options = new List<List<string>>();
    options.Add(new List<string> { "senior", "adult", "kid" });
    options.Add(new List<string> { "blue", "red", "green"});
    options.Add(new List<string> {"money", "trees", "plants"});

    bool exists = variants.Any(a => options.Any(b => b.SequenceEqual(a.OrderBy(x => x))));

    Console.WriteLine(exists);
    // The result should be TRUE even though the order of "senior", "adult" and "kid"
    // is different and that the order of listed items is different


 //TEST 2
    List<List<string>> options2 = new List<List<string>>();
    options2.Add(new List<string> { "senior", "adult", "kid" });
    options2.Add(new List<string> { "orange", "red", "green"});
    options2.Add(new List<string> {"money", "trees", "plants"});

    exists = variants.Any(a => options2.Any(b => b.SequenceEqual(a.OrderBy(x => x))));

    Console.WriteLine(exists);
    // The result should be FALSE. All listed options are TRUE except that the 2nd list has
    // "orange" which doesn't appear in the variants list.



 //TEST 3
    List<List<string>> options3 = new List<List<string>>();
    options3.Add(new List<string> { "senior", "red", "adult" });
    options3.Add(new List<string> { "blue", "kid", "green"});
    options3.Add(new List<string> {"money", "trees", "plants"});

    exists = variants.Any(a => options3.Any(b => b.SequenceEqual(a.OrderBy(x => x))));

    Console.WriteLine(exists);
    // The result should be FALSE. All of the items actually exist in the variant list, 
    // but "senior", "kid", and "adult" do not appear together within a list of variants.

3 个答案:

答案 0 :(得分:3)

您可以为每个变体列表构建一个HashSet,然后检查每个选项列表,至少一个变体集包含所有选项:

List<HashSet<string>> variantSets = variants.Select(vl => new HashSet<string>(vl)).ToList();

bool allIncluded = options.All(ol => variantSets.Any(vs => ol.All(vs.Contains)));

Link to Fiddle

答案 1 :(得分:2)

到目前为止,您的代码已经可以使用了,但是两个列表都应该在比较中进行排序。

之前:

bool exists = variants.Any(a => options.Any(b => b.SequenceEqual(a.OrderBy(x => x))));

已修复:

bool exists = options.All(a => variants.Any(b => b.OrderBy(x => x).SequenceEqual(a.OrderBy(x => x))));

答案 2 :(得分:2)

我建议您对选项/变体使用HashSet<T>而不是List<T>,因为您在此处设置了语义,而不是列出语义:选项只能出现一次且顺序不重要

例如:

 var variants = new List<HashSet<string>>();
 variants.Add(new HashSet<string> {"cars", "boats", "planes"});
 variants.Add(new HashSet<string> {"money", "trees", "plants"});
 variants.Add(new HashSet<string> {"green", "blue", "red" });
 variants.Add(new HashSet<string> {"kid", "adult", "senior"});
 variants.Add(new HashSet<string> {"tax", "insurance", "salary"});

您的检查是倒退的:您想检查所有选项是否与任何变体匹配。因此,您需要从选项开始。 HashSet<T>有一种检查集合是否相等的方法,因此您可以使用此方法:

bool exists = options.All(option => variants.Any(option.SetEquals));