Je joue avec LINQ pour en savoir plus, mais je ne sais pas comment l'utiliser Distinct
quand je n'ai pas de liste simple (une simple liste d'entiers est assez facile à faire, ce n'est pas la question). Que dois-je faire si je veux utiliser Distinct sur une liste d'objets sur une ou plusieurs propriétés de l'objet?
Exemple: Si un objet l'est Person
, avec Propriété Id
. Comment puis-je obtenir toutes les personnes et les utiliser Distinct
avec la propriété Id
de l'objet?
Person1: Id=1, Name="Test1"
Person2: Id=1, Name="Test1"
Person3: Id=2, Name="Test2"
Comment puis-je obtenir juste Person1
et Person3
? Est-ce possible?
Si ce n'est pas possible avec LINQ, quelle serait la meilleure façon d'avoir une liste en Person
fonction de certaines de ses propriétés dans .NET 3.5?
GroupBy
est plus simple. Si vous en avez besoin à plus d'un endroit, il est beaucoup plus propre (OMI) d'encapsuler l'intention.IQueryable<T>
ici, je ne vois pas en quoi c'est pertinent. Je suis d'accord que cela ne conviendrait pas pour EF, etc., mais dans LINQ to Objects, je pense que c'est plus approprié queGroupBy
. Le contexte de la question est toujours important.Facile! Vous voulez les regrouper et choisir un gagnant dans le groupe.
Si vous souhaitez définir des groupes sur plusieurs propriétés, voici comment:
la source
Single()
etSingleOrDefault()
chaque lancer lorsque la source a plus d'un élément. Dans cette opération, nous nous attendons à la possibilité que chaque groupe puisse avoir plus d'un élément. D'ailleurs,First()
est préférable àFirstOrDefault()
parce que chaque groupe doit avoir au moins un membre .... à moins que vous n'utilisiez EntityFramework, qui ne peut pas comprendre que chaque groupe a au moins un membre et demandeFirstOrDefault()
.FirstOrDefault()
github.com/dotnet/efcore/issues/12088 Je suis sur 3.1 et j'obtiens des erreurs "incapable de traduire".Utilisation:
Le
where
vous aide à filtrer les entrées (pourrait être plus complexe)groupby
et àselect
effectuer la fonction distincte.la source
Vous pouvez également utiliser la syntaxe de requête si vous souhaitez qu'elle ressemble à LINQ:
la source
Je pense que cela suffit:
la source
Solution, regroupez d'abord vos champs, puis sélectionnez le premier élément par défaut.
la source
Vous pouvez le faire avec la norme
Linq.ToLookup()
. Cela créera une collection de valeurs pour chaque clé unique. Sélectionnez simplement le premier article de la collectionla source
Le code suivant est fonctionnellement équivalent à la réponse de Jon Skeet .
Testé sur .NET 4.5, devrait fonctionner sur n'importe quelle version antérieure de LINQ.
Soit dit en passant, consultez la dernière version de Jon Skeet de DistinctBy.cs sur Google Code .
la source
J'ai écrit un article qui explique comment étendre la fonction Distinct afin que vous puissiez faire comme suit:
Voici l'article: Extension de LINQ - Spécification d'une propriété dans la fonction distincte
la source
Personnellement, j'utilise la classe suivante:
Ensuite, une méthode d'extension:
Enfin, l'usage prévu:
L'avantage que j'ai trouvé en utilisant cette approche est la réutilisation de la
LambdaEqualityComparer
classe pour d'autres méthodes qui acceptent unIEqualityComparer
. (Oh, et je laisse leyield
truc à l'implémentation LINQ originale ...)la source
Si vous avez besoin d'une méthode Distinct sur plusieurs propriétés, vous pouvez consulter mes PowerfulExtensions bibliothèque . Actuellement, c'est à un stade très jeune, mais vous pouvez déjà utiliser des méthodes telles que Distinct, Union, Intersect, Except sur un certain nombre de propriétés;
Voici comment vous l'utilisez:
la source
Lorsque nous avons été confrontés à une telle tâche dans notre projet, nous avons défini une petite API pour composer des comparateurs.
Donc, le cas d'utilisation était comme ceci:
Et l'API elle-même ressemble à ceci:
Plus de détails sont sur notre site: IEqualityComparer dans LINQ .
la source
Vous pouvez utiliser DistinctBy () pour obtenir des enregistrements Distinct par une propriété d'objet. Ajoutez simplement la déclaration suivante avant de l'utiliser:
puis l'utiliser comme suit:
où 'Index' est la propriété sur laquelle je veux que les données soient distinctes.
la source
Vous pouvez le faire (mais pas très vite) comme ceci:
Autrement dit, "sélectionnez toutes les personnes où il n'y a pas une autre personne différente dans la liste avec le même ID."
Remarquez, dans votre exemple, que cela ne ferait que sélectionner la personne 3. Je ne sais pas comment dire ce que vous voulez, parmi les deux précédents.
la source
Si vous ne voulez pas ajouter la bibliothèque MoreLinq à votre projet juste pour obtenir la
DistinctBy
fonctionnalité, vous pouvez obtenir le même résultat final en utilisant la surcharge de laDistinct
méthode de Linq qui prend unIEqualityComparer
argument.Vous commencez par créer une classe de comparaison d'égalité personnalisée générique qui utilise la syntaxe lambda pour effectuer une comparaison personnalisée de deux instances d'une classe générique:
Ensuite, dans votre code principal, vous l'utilisez comme suit:
Voila! :)
Ce qui précède suppose ce qui suit:
Person.Id
est de typeint
people
collection ne contient aucun élément nulSi la collection peut contenir des valeurs nulles, réécrivez simplement les lambdas pour vérifier la valeur null, par exemple:
ÉDITER
Cette approche est similaire à celle de la réponse de Vladimir Nesterovsky mais plus simple.
Il est également similaire à celui de la réponse de Joel mais permet une logique de comparaison complexe impliquant plusieurs propriétés.
Cependant, si vos objets ne peuvent différer que par
Id
un autre utilisateur, la réponse correcte est que tout ce que vous devez faire est de remplacer les implémentations par défaut deGetHashCode()
etEquals()
dans votrePerson
classe, puis d'utiliser simplement laDistinct()
méthode prête à l'emploi de Linq pour filtrer tous les doublons.la source
La meilleure façon de le faire qui sera compatible avec d'autres versions de .NET est de remplacer Equals et GetHash pour gérer cela (voir la question Stack Overflow Ce code renvoie des valeurs distinctes. Cependant, ce que je veux, c'est renvoyer une collection fortement typée par opposition à un type anonyme ), mais si vous avez besoin de quelque chose de générique dans votre code, les solutions de cet article sont excellentes.
la source
la source
Select()
new Person
lieu denew Player
? Cependant, le fait que vous passiez une commandeID
n'indique pasDistinct()
d'utiliser cette propriété pour déterminer l'unicité, donc cela ne fonctionnera pas.Substituez les méthodes Equals (object obj) et GetHashCode () :
puis appelez simplement:
la source
Vous devriez pouvoir remplacer Equals on person pour réellement faire Equals on Person.id. Cela devrait entraîner le comportement que vous recherchez.
la source
Veuillez essayer avec le code ci-dessous.
la source