Linq'te tablonun yalnızca bir alanına dayalı olarak ayırt edilebilir


133

Linq'te tablonun bir alanına dayalı olarak sonuç almak için .distinct'i kullanmaya çalışıyorum (bu nedenle tablodan tamamen çoğaltılmış kayıtlar gerektirmez).

Aşağıdaki gibi farklı kullanarak temel sorgu yazdığımı biliyorum:

var query = (from r in table1
orderby r.Text
select r).distinct();

ancak r.textyinelenmeyen sonuçlara ihtiyacım var .


Sen ayrı olmak istediğini alan belirtmek gerekir, bkz msdn.microsoft.com/en-us/library/bb348436.aspx
Antarr Byrd

Yanıtlar:


300

Bunu dene:

table1.GroupBy(x => x.Text).Select(x => x.FirstOrDefault());

Bu, tabloyu gruplandıracak ve Texther gruptan ilk satırı kullanacak ve Textfarklı olan satırlarla sonuçlanacaktır .


2
Groupby'de 1'den fazla alan varsa ne olur?

6
@ user585440: Bu durumda, şu şekilde anonim bir tür kullanırsınız:table1.GroupBy(x => new { x.Text, x.Property2, x.Property3 }).Select(x => x.First());
Daniel Hilgarth

2
Evet, haklısın ve ben onu çoktan buldum. Yine de teşekkürler. Ayrıca Select (x => x.First ()) öğesinin çökmeye neden olabileceğini görüyorum. Select (x => x.FirstOrDefault ()) olarak değiştirmek daha iyidir;

6
FirstOrDefault'u kullanmak zorunda kaldım yoksa bir çalışma zamanı hatası
oluştu

2
@ TruthOf42 Bu pek olası değil. GroupByboş gruplar oluşturmaz, önceki yorumuma bakın. Büyük olasılıkla, kodunuz burada gördüğünüzden daha fazlasını içeriyor. Belki senin de bir Wheredurumun ya da şartın var First.
Daniel Hilgarth

26

MoreLinq'in kullanabileceğiniz bir DistinctBy yöntemi vardır:

Şunları yapmanıza izin verecektir:

var results = table1.DistictBy(row => row.Text);

Yöntemin uygulanması (bağımsız değişken doğrulamasının kısaltması) aşağıdaki gibidir:

private static IEnumerable<TSource> DistinctByImpl<TSource, TKey>(IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
    HashSet<TKey> knownKeys = new HashSet<TKey>(comparer);
    foreach (TSource element in source)
    {
        if (knownKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}

üzgünüm equalityComparer'ı kullanmaya istekli değildim.
Megha Jain

@MeghaJain Biri ne olursa olsun, GroupByihtiyaç duyulduğu gibi kullanılacak . EqualityComparerHiçbiri sağlanmadıysa her iki yöntem de varsayılanı kullanır .
2013

9
Peki, yanılıyorsam düzeltin, ama buradaki bu ayrım DB'de değil bellekte yapılır? Bu, istenmeyen tam taramaya yol açmaz mı?
Kek

@Kek. Hayır, getiri getirisi nedeniyle, ilk belirgin öğede duracaksınız. Sonunda, evet, her anahtarı HashSet'e yükleyeceksiniz, ancak IEnumerable ve IEnumerable olduğu için yalnızca bu öğeleri alacaksınız. LINQ to SQL'den bahsediyorsanız, evet, bu bir tablo taraması yapacak.
PRMan

12

ancak r.text'in yinelenmediği sonuçlara ihtiyacım var

Bunu istiyormuşsun gibi geliyor:

table1.GroupBy(x => x.Text)
      .Where(g => g.Count() == 1)
      .Select(g => g.First());

Bu Text, benzersiz olan satırları seçecektir .


7

Daniel Hilgarth'ın yukarıdaki yanıtı, Entity-FrameworkSystem.NotSupported ile ilgili bir istisnaya yol açar . Entity-Framework ile şu şekilde olmalıdır:

table1.GroupBy(x => x.Text).Select(x => x.FirstOrDefault());

3

Bu konuyla ilgili çok sayıda tartışma var.

Bunlardan birini burada bulabilirsiniz :

En popüler önerilerden biri, @Servy'nin de belirttiği gibi bir lambda ifadesini parametre olarak alan Distinct yöntemidir.

C #'ın baş mimarı Anders Hejlsberg burada çözümü önerdi . Ayrıca, çerçeve tasarım ekibinin neden lambda alan bir Distinct yöntemi aşırı yüklemesi eklememeye karar verdiğini açıklıyor.


2

Bulduğuma göre, sorgunuz çoğunlukla doğru. Sadece "r'yi seç" i "r.Metni seç" olarak değiştirin, hepsi budur ve bu sorunu çözecektir. MSDN, nasıl çalışması gerektiğini bu şekilde belgeledi.

Ör:

    var query = (from r in table1 orderby r.Text select r.Text).distinct();

bu durumda
istenmeyebilecek

1
data.Select(x=>x.Name).Distinct().Select(x => new SelectListItem { Text = x });

-2

bu kodu deneyin:

table1.GroupBy(x => x.Text).Select(x => x.FirstOrDefault());

-5

Bunu deneyebilirsiniz:table1.GroupBy(t => t.Text).Select(shape => shape.r)).Distinct();

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.