2012-08-04 12 views
19

Ich habe eine list<message>, die Eigenschaften des Typs Guid und DateTime (sowie andere Eigenschaften) enthält. Ich möchte alle Elemente in dieser Liste loswerden, wo die Guid und DateTime die gleichen sind (außer einem). Es wird Zeiten geben, wenn diese beiden Eigenschaften sind die gleichen wie andere Elemente in der Liste, aber die anderen Eigenschaften werden anders sein, so kann ich einfach nicht .Distinct()Wählen Sie distinct durch zwei Eigenschaften in einer Liste

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?); 

verwenden Dies ist, was ich jetzt haben, aber es scheint, wie es solle einen besseren Weg

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++ 
    } 
} 
+1

http://stackoverflow.com/questions/489258/linq-distinct-on-a-particular-property – Shyju

+0

Dank. Ich weiß nicht, warum ich das nicht gefunden habe, als ich gesucht habe. – user1304444

+0

Ich bin froh, dass Jons Antwort für dich funktioniert hat. Nur eine Anmerkung der Vorsicht: Ihre "aktuell verwendete Methode" kompiliert nicht, und (nach der Behebung der Kompilierungsfehler) wird es nicht in allen Fällen funktionieren - abhängig von der Reihenfolge Ihrer Elemente würden Sie anders werden ** (falsch) ** Ergebnisse (schließlich vergleichen Sie nur benachbarte Elemente miteinander). – Adam

Antwort

52

LINQ to Objects wird nicht über diese Funktionalität leicht in einem integrierten Weg, aber MoreLINQ hat eine handliche DistinctBy Methode:

messages = messages.DistinctBy(m => new { m.id, m.date }).ToList(); 
+0

Ich nehme an, dass MoreLINQ kostenlos ist? Ich sehe das nicht explizit irgendwo auf der Seite geschrieben. – user1304444

+2

@ user1304444: Es ist eine Open-Source-Bibliothek - siehe den Link "Apache License 2.0" auf der linken Seite der Seite. –

+3

Für alle anderen, die diese Frage sehen, scheint der oben erwähnte Link Shyju auch eine gute Antwort zu sein. http://stackoverflow.com/questions/489258/linq-distinct-on-a-particular-property – user1304444

2

Was ist damit?

var messages = messages 
       .GroupBy(m => m.id) 
       .GroupBy(m => m.date) 
       .Select(m => m.First()); 
+0

kompiliert nicht ... Denken Sie daran, dass GroupBy eine 'IGrouping' zurückgibt. – Adam

+0

Dieser Ansatz ist gültig, wenn HashSet nicht auf der Plattform vorhanden ist, die Sie wie silverslight entwickeln .... – Thomas

11

Jon Skeet DistinctBy ist definitiv der Weg zu gehen, aber wenn Sie Ihre eigene Erweiterungsmethode interessiert sind bei der Definition Sie könnten in dieser prägnanten Version Phantasie nehmen:

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))); 
} 

, die die gleiche Signatur :

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

Ich weiß, das ist alt, aber bitte beachten Sie, dass Sie nach Aufruf von 'DistinctBy()' 'ToList()' oder 'ToArray()' aufrufen müssen. Wenn Sie direkt an IEnumerable arbeiten und es mehrmals aufzählen, funktioniert es nicht, da die Elemente zum HashSet hinzugefügt werden, während Sie das IEnumerable zum ersten Mal durchlaufen und nicht ein zweites Mal zurückgegeben werden. wie in dieser [.NET Fiddle] (https://dotnetfiddle.net/5PUJxl) gezeigt. – fknx

1

Sie können meine PowerfulExtensions Bibliothek auszuchecken. Derzeit ist es in einem sehr jungen Stadium, aber Sie können bereits Methoden wie Distinct, Union, Intersect, außer einer beliebigen Anzahl von Eigenschaften verwenden; Diese

ist, wie Sie es verwenden:

using PowerfulExtensions.Linq; 
... 
var distinct = myArray.Distinct(x => x.A, x => x.B); 
Verwandte Themen