简体   繁体   中英

C# Linq Check if List of List is inside List of List

I have two Lists of Lists:
(1) variants and (2) options .

I need to see if ALL of options exists inside variants (regardless of order).

For Example: in the code below I need to make sure each list of items appears in the variants list - so the list "blue", "red" "green" must appear in the variants list regardless of order

EDIT (clarification): All of the lists inside of "options" must appear in "variants". If one of them fails then the boolean must return false.

I setup a LINQ condition but I'm not sure why its not working. Any help would be appreciated.

 //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.

You can build a HashSet for each variants list and then check for each options list at least one variant set contains all the options:

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

Your code works so far, but both lists should be sorted within the comparison.

before:

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

fixed:

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

I'd suggest you use HashSet<T> rather than List<T> for the options / variants, as you have set semantics here rather than list semantics: options can only appear once & the order isn't important.

For example:

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

And your check is backwards: you want to check if all options match any of the variants. So you need to start with options. HashSet<T> has a method to check if the sets are equal, so you can use this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM