1407 votes

Linq Distinctes sur une Propriété particulière

Je suis à jouer avec Linq pour apprendre à ce sujet, mais je ne peux pas comprendre comment Distincts, alors que je n'ai pas de liste simple (une simple liste d'entiers est très facile à faire, ce n'est pas la question). Et si voulez distinctes, une liste d'Objet sur UNE ou PLUSIEURS Propriétés de l'objet?

Exemple: Si un objet est une "Personne", avec la Propriété "Id". Comment puis-je obtenir de toute Personne et distincts entre eux par l'Id de propriété de l'objet?

Person1: Id=1, Name="Test1"
Person2: Id=1, Name="Test1"
Person3: Id=2, Name="Test2"

Comment puis-je obtenir juste Personne1 et Person3? Est-ce possible?

Si il n'est pas possible avec Linq, quel serait le meilleur moyen d'avoir une liste de "Personne", en fonction de certaines de ses Propriétés .Net 3.5?

2329voto

David B Points 53123

Et si voulez distinctes, une liste d'Objet sur UNE ou PLUSIEURS Propriétés de l'objet?

Simple! Vous souhaitez les regrouper et de choisir un gagnant de groupe.

List<Person> distinctPeople = allPeople
  .GroupBy(p => p.PersonId)
  .Select(g => g.First())
  .ToList();

Si vous souhaitez définir des groupes sur de multiples propriétés, voici comment:

List<Person> distinctPeople = allPeople
  .GroupBy(p => new {p.PersonId, p.FavoriteColor} )
  .Select(g => g.First())
  .ToList();

1491voto

Jon Skeet Points 692016

EDIT: C'est fait maintenant partie de MoreLINQ.

Ce que vous avez besoin est un "distincte" de manière efficace. Je ne crois pas que c'est une partie de LINQ comme il est, même s'il est assez facile d'écrire:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>
    (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    HashSet<TKey> seenKeys = new HashSet<TKey>();
    foreach (TSource element in source)
    {
        if (seenKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}

Donc, pour trouver les valeurs distinctes en utilisant seulement l' Id de la propriété, vous pouvez utiliser:

var query = people.DistinctBy(p => p.Id);

Et pour l'utilisation de plusieurs propriétés, vous pouvez utiliser les types anonymes, qui mettent en œuvre l'égalité de façon appropriée:

var query = people.DistinctBy(p => new { p.Id, p.Name });

Pas testé, mais ça devrait fonctionner (et maintenant au moins compile).

Il suppose le comparateur par défaut pour les clés - si vous voulez passer un comparateur d'égalité, il suffit de passer à l' HashSet constructeur.

119voto

karcsi Points 53

comment à ce sujet:

List<Person> pList = new List<Person>();
/* fill list */

var result = pList.Where(p => p.Name != null).GroupBy(p => p.Id).Select(grp => grp.First());

La où vous aide à filtrer les entrées (peut être plus complexe) et à l'égard du groupe et sélectionnez exécuter la fonction distinct. Espérons que cette aide

88voto

Chuck Rostance Points 1377

Vous pouvez également utiliser la syntaxe si vous voulez qu'il regarde de tous linq comme:

var uniquePeople = from p in people
                   group p by new {p.ID} //or group by new {p.ID, p.Name, p.Whatever}
                   into mygroup
                   select mygroup.FirstOrDefault();

21voto

Contango Points 7976

Le code suivant est fonctionnellement équivalent à Jon Skeet la réponse ci-dessus.

Testé sur .NET 4.5, devrait fonctionner sur toute version antérieure de LINQ.

public static IEnumerable<TSource> DistinctBy2<TSource, TKey>(
  this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
  HashSet<TKey> seenKeys = new HashSet<TKey>();
  return source.Where(element => seenKeys.Add(keySelector(element)));
}

Incidentially, découvrez Jon Skeet la dernière version de DistinctBy.cs sur Google Code.

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