web-dev-qa-db-fra.com

Sélectionner distinct par deux propriétés dans une liste

J'ai un list<message> qui contient des propriétés de type Guid et DateTime (ainsi que d'autres propriétés). Je voudrais supprimer tous les éléments de cette liste où Guid et DateTime sont les mêmes (sauf un). Il y aura des moments où ces deux propriétés seront identiques aux autres éléments de la liste, mais les autres propriétés seront différentes, je ne peux donc pas simplement utiliser .Distinct().

List<Message> messages = GetList();
//The list now contains many objects, it is ordered by the DateTime property

messages = from p in messages.Distinct(  what goes here? ); 

C’est ce que j’ai en ce moment, mais il me semble qu’il devrait exister un meilleur moyen

List<Message> messages = GetList();

for(int i = 0; i < messages.Count() - 1)  //use Messages.Count() -1 because the last one has nothing after it to compare to
{
    if(messages[i].id == messages[i+1}.id && messages[i].date == message[i+1].date)
    {
        messages.RemoveAt(i+1);
    {
    else
    {
         i++
    }
}
22
user1304444

LINQ to Objects ne fournit pas facilement cette fonctionnalité de manière intégrée, mais MoreLINQ a une méthode pratique DistinctBy:

messages = messages.DistinctBy(m => new { m.id, m.date }).ToList();
61
Jon Skeet

La variable DistinctBy de Jon Skeet est sans aucun doute la voie à suivre. Toutefois, si vous êtes intéressé par la définition de votre propre méthode d'extension, vous pourriez en prendre une version plus concise:

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

qui a la même signature:

messages = messages.DistinctBy(x => new { x.id, x.date }).ToList();
14
Adam

Et ça?

var messages = messages
               .GroupBy(m => m.id)
               .GroupBy(m => m.date)
               .Select(m => m.First());
2
Andrew Church

Essaye ça,

 var messages = (from g1 in messages.GroupBy(s => s.id) from g2 in g1.GroupBy(s => s.date) select g2.First()).ToList();
1
Manish Agarwal

Vous pouvez consulter mon PowerfulExtensions library. Actuellement, il est encore très jeune, mais vous pouvez déjà utiliser des méthodes telles que Distinct, Union, Intersect, Sauf sur un nombre quelconque de propriétés;

Voici comment vous l'utilisez:

using PowerfulExtensions.Linq;
...
var distinct = myArray.Distinct(x => x.A, x => x.B);
1
Andrzej Gis