8 votes

Distinct dans le cadre d'Entity

J'ai une liste d'objets dont certains ont la même identité. J'aimerais donc supprimer les éléments qui sont en double.

J'ai essayé avec quelque chose comme ça :

List<post> posts = postsFromDatabase.Distinct().ToList();

Mais ça ne marche pas !

J'ai donc écrit cette méthode afin d'éviter les doublons :

public List<Post> PostWithOutDuplicates(List<Post> posts)
    {
        List<Post> postWithOutInclude = new List<Post>();
        var noDupes = posts.Select(x => x.Id).Distinct();
        if (noDupes.Count() < posts.Count)
        {
            foreach (int idPost in noDupes)
            {
                postWithOutInclude.Add(posts.Where(x => x.Id == idPost).First());
            }
            return postWithOutInclude;
        }
        else
        {
            return posts;
        }
    }

Des idées pour améliorer les performances ?

Merci d'avance.

31voto

Piotr Justyna Points 2140

C'est simple et facile :

List<Post> posts = posts
.GroupBy(x => x.Id)
.Select(x => x.FirstOrDefault())

Mais si vous voulez l'écrire correctement, je vous conseille de l'écrire comme ceci :

public class PostComparer : IEqualityComparer<Post>
{
    #region IEqualityComparer<Post> Members

    public bool Equals(Post x, Post y)
    {
        return x.Id.Equals(y.Id);
    }

    public int GetHashCode(Post obj)
    {
        return obj.Id.GetHashCode();
    }

    #endregion
}

Comme cela vous donnera plus de liberté quand il s'agit de comparaisons supplémentaires. Ayant écrit cette classe, vous pouvez l'utiliser comme ceci :

List<Post> posts = postsFromDatabase.Distinct(new PostComparer()).ToList();

5voto

Jonathan Points 6611

Je pense qu'écrire votre propre comparateur personnalisé est une bonne approche.

Voici un article de msdn qui explique très bien le sujet : http://support.microsoft.com/kb/320727

La raison pour laquelle les Distinct ne fonctionnent pas est que Distinct() n'a aucune idée de la façon de déterminer s'il y a des égaux, donc il utilise la référence pour déterminer s'il s'agit du même "objet". Il fonctionne comme il est censé le faire. Toutes les classes dans la requête ne sont pas le même objet.

En écrivant votre propre comparateur (c'est facile), vous pouvez indiquer à Distinct() comment effectuer la comparaison pour déterminer s'ils sont égaux.

Editar : Si ne pas utiliser Distinct n'est pas un problème et que la situation n'est pas fréquente, la première réponse de Piotr Justyna est simple et efficace.

0voto

Brian Points 1662

Au lieu de .First(), essayez .FirstOrDefault()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X