web-dev-qa-db-fra.com

Vérifier si deux listes sont égales

J'ai un cours comme suit:

public class Tag {
    public Int32 Id { get; set; }
    public String Name { get; set; }
}

Et j'ai deux listes de balises:

List<Tag> tags1;
List<Tag> tags2;

J'ai utilisé LINQ pour sélectionner les identifiants de chaque liste de balises. Puis:

List<Int32> ids1 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids2 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids3 = new List<Int32> { 2, 1, 3, 4 };
List<Int32> ids4 = new List<Int32> { 1, 2, 3, 5 };
List<Int32> ids5 = new List<Int32> { 1, 1, 3, 4 };

ids1 devrait être égal à ids2 et ids3 ... Les deux ont les mêmes numéros.

ids1 ne doit pas être égal à ids4 et à ids5 ...

J'ai essayé ce qui suit:

var a = ints1.Equals(ints2);
var b = ints1.Equals(ints3);

Mais les deux me donnent de faux.

Quel est le moyen le plus rapide de vérifier si les listes de balises sont égales?

UPDATE

Je cherche des POSTS dont les balises sont exactement les mêmes que les balises dans un livre.

IRepository repository = new Repository(new Context());

IList<Tags> tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } };

Book book = new Book { Tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } } };

var posts = repository
  .Include<Post>(x => x.Tags)
  .Where(x => new HashSet<Int32>(tags.Select(y => y.Id)).SetEquals(book.Tags.Select(y => y.Id)))
  .ToList();

J'utilise Entity Framework et j'obtiens l'erreur suivante:

Une exception de type 'System.NotSupportedException' s'est produite dans mscorlib.dll mais n'a pas été gérée dans le code utilisateur

Informations complémentaires: LINQ to Entities ne reconnaît pas la méthode 'Boolean SetEquals (System.Collections.Generic.IEnumerable`1 [System.Int32])' 'et ne peut pas être traduite en expression de magasin.

Comment résoudre ce problème?

147
Miguel Moura

Utilisez SequenceEqual pour vérifier l’égalité de séquence car la méthode Equals recherche l’égalité de référence .

_var a = ints1.SequenceEqual(ints2);
_

Ou si vous ne vous souciez pas de l'ordre des éléments, utilisez la méthode Enumerable.All :

_var a = ints1.All(ints2.Contains);
_

La deuxième version requiert également une autre vérification de Count car elle renverrait true même si _ints2_ contient plus d'éléments que _ints1_. Donc, la version la plus correcte serait quelque chose comme ceci:

_var a = ints1.All(ints2.Contains) && ints1.Count == ints2.Count;
_

Pour vérifier l'inégalité , inversez simplement le résultat de la méthode All:

_var a = !ints1.All(ints2.Contains)
_
270
Selman Genç

List<T> égalité ne les vérifie pas élément par élément. Vous pouvez utiliser méthode SequenceEqual de LINQ pour cela:

var a = ints1.SequenceEqual(ints2);

Pour ignorer l'ordre, utilisez SetEquals:

var a = new HashSet<int>(ints1).SetEquals(ints2);

Cela devrait fonctionner, car vous comparez des séquences d’ID qui ne contiennent pas de doublons. Si tel est le cas et que vous devez prendre en compte les doublons, vous devez composer un dictionnaire de comptes basé sur un hachage en temps linéaire, en ajouter un pour chaque élément de la première séquence, soustraire un pour chaque élément de la seconde. séquence et vérifiez si les nombres résultants sont tous des zéros:

var counts = ints1
    .GroupBy(v => v)
    .ToDictionary(g => g.Key, g => g.Count());
var ok = true;
foreach (var n in ints2) {
    int c;
    if (counts.TryGetValue(n, out c)) {
        counts[n] = c-1;
    } else {
        ok = false;
        break;
    }
}
var res = ok && counts.Values.All(c => c == 0);

Enfin, si vous avez une solution O(N*LogN), vous pouvez trier les deux séquences et les comparer pour l’égalité à l’aide de SequenceEqual.

103
dasblinkenlight
Enumerable.SequenceEqual(FirstList.OrderBy(fElement => fElement), 
                         SecondList.OrderBy(sElement => sElement))
24
Pankaj