2012-08-04 42 views
19

Guid ve DateTime (ve diğer özelliklerin yanı sıra) özellikleri içeren list<message> var. Guid ve DateTime'un aynı (tümü hariç) olduğu listedeki tüm öğelerden kurtulmak istiyorum. Orada şu iki özelliği listedeki diğer öğeleri aynı olacaktır zamanlar olacaktır, ancak diğer özellikler farklı olacaktır, bu yüzden sadece bu şu anda ne var .Distinct()Bir listedeki iki özelliğe göre farklı seç

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

kullanamaz, ama sanki orada

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

Teşekkür:

Bu kullanmadan nasıl. Aradığımda neden bulamadığımı bilmiyorum. – user1304444

+0

Jon'un cevabı senin için çalıştığı için memnunum. Sadece bir dikkat notu: "şu anda kullanılan yönteminiz" derlemez ve (derleme hatalarını düzelttikten sonra) her durumda çalışmayacaktır - öğelerinizin sırasına bağlı olarak, farklı olur ** (yanlış) ** sonuçlar (sonuçta, sadece bitişik elemanları birbirinizle karşılaştırıyorsunuz). – Adam

cevap

52

Nesneler LINQ yerleşik bir şekilde kolayca bu işlevselliği sağlamaz daha iyi bir yol olması gerektiğini görünüyor ama MoreLINQ kullanışlı DistinctBy yöntemi vardır:

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

MoreLINQ kullanımının ücretsiz olduğunu mu varsayıyorum? Bu sayfada açıkça yazılı olanları göremiyorum. – user1304444

+2

@ user1304444: Açık kaynak kodlu bir kütüphanedir - sayfanın solundaki "Apache License 2.0" bağlantısına bakın. –

+3

Bu soruyu görüntüleyen herkes için, yukarıda bahsedilen Shyju'nun bağlantısı da büyük bir cevap gibi görünüyor. http://stackoverflow.com/questions/489258/linq-distinct-on-a-particular-property – user1304444

2

Buna ne dersiniz? Aynı imzası vardır

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

:

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

derlemiyor ... GroupBy'nin bir "Gruplama" döndürdüğünü unutmayın. – Adam

+0

Bu yaklaşım, HashSet , silverslight gibi geliştirdiğiniz plaka formunda mevcut değilse geçerlidir. – Thomas

11

Jon Skeet en DistinctBy Bunu daha özlü sürümde fantezi alabilir kendi abone yöntemi tanımlayan ilgilenen ancak eğer kesinlikle gitmek yoludur :

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

Bunun eski olduğunu biliyorum, ancak DistinctBy() 'yi çağırdıktan sonra' ToList() 'veya' ToArray() 'işlevini çağırmanız gerektiğini lütfen unutmayın. Doğrudan 'IEnumerable' üzerinde çalışıyorsanız ve birden çok kez numaralandırıyorsanız, öğeler ilk kez 'IEnumerable' üzerinden geçerken ikinci kez iade edilmeyecek 'HashSet'e eklendiğinden işe yaramaz. Bu [.NET Fiddle] 'da gösterildiği gibi (https://dotnetfiddle.net/5PUJxl). – fknx

1

Sen benim PowerfulExtensions kütüphane kontrol edebilirsiniz. Şu anda çok genç bir aşamada, ancak zaten herhangi bir sayıda özellik dışında Distinct, Union, Kesişim, gibi yöntemleri kullanabilirsiniz;

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