2
votes

C # Linq Vérifier si la liste de la liste est à l'intérieur de la liste de la liste

J'ai deux listes de listes:
(1) variantes et (2) options .

J'ai besoin de voir si TOUTES les options existent dans les variantes (quel que soit l'ordre).

Par exemple: dans le code ci-dessous, je dois m'assurer que chaque liste d'éléments apparaît dans la liste des variantes - donc la liste "bleu", "rouge" "vert" doit apparaître dans la liste des variantes indépendamment de ordre

MODIFIER (clarification): Toutes les listes à l'intérieur des "options" doivent apparaître dans "variantes". Si l'un d'entre eux échoue, le booléen doit retourner false.

J'ai configuré une condition LINQ mais je ne sais pas pourquoi cela ne fonctionne pas. Toute aide serait appréciée.

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


1 commentaires

Vous ne triez que la variante, pas l'option. Comme aucune des options n'est en ordre, vous n'obtiendrez aucune correspondance. Je vous suggère d'utiliser par exemple HashSet et SetEquals ici, car vous avez vraiment des ensembles plutôt que des listes.


3 Réponses :


3
votes

Vous pouvez créer un HashSet pour chaque liste de variantes, puis vérifier pour chaque liste d'options au moins un ensemble de variantes contient toutes les 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)));

Lien vers Fiddle


2 commentaires

C'est parfait!


@bagofmilk Notez que cela fonctionnera également s'il y a plus de variantes que d'options dans un ensemble donné.



2
votes

Votre code fonctionne jusqu'à présent, mais les deux listes doivent être triées dans la comparaison.

avant:

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

corrigé:

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


2 commentaires

C'est sooooo proche de ce dont j'ai besoin - mais j'ai besoin de la fonction pour m'assurer que tous les éléments de la liste existent - pour l'instant, il ne vérifie que si 1 d'entre eux est vrai.


peut-être avec celui-ci? :) bool exists = options.All (a => variants.Any (b => b.OrderBy (x => x) .SequenceEqual (a.OrderBy (x => x))));



3
votes

Je vous suggère d'utiliser HashSet plutôt que List pour les options / variantes, car vous avez défini la sémantique ici plutôt que la sémantique de la liste: les options ne peuvent apparaître qu'une seule fois et l'ordre n'est pas important.

Par exemple:

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

Et votre vérification est inversée: vous voulez vérifier si toutes les options correspondent à l'une des les variantes. Vous devez donc commencer par des options. HashSet a une méthode pour vérifier si les ensembles sont égaux, vous pouvez donc utiliser ceci:

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


0 commentaires