Gruplama ile bir listede bir sözlük oluşturun


106

Listede aşağıdaki nesne var:

public class DemoClass
{
    public int GroupKey { get; set; }
    public string DemoString { get; set; }
    public object SomeOtherProperty { get; set; }
}

Şimdi, bundan şu sözlüğü oluşturmak istiyorum:

Dictionary<int, List<DemoClass>>

List<DemoClass>Mülke göre gruplamak istiyorum GroupKey, ancak bunun nasıl yapıldığını ve biraz yardımcı olduğunu anlamıyorum.

Biraz düşündükten sonra gerekli davranışa şu şekilde ulaştım:

var groupedDemoClasses = from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                            group demoClass by demoClass.GroupKey
                            into groupedDemoClass
                            select groupedDemoClass;
var neededDictionary = groupedDemoClass.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

ama bunu tek bir ifade haline getirmenin bir yolu var mı?

Yanıtlar:


88
var groupedDemoClasses = (from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                          group demoClass by demoClass.GroupKey
                          into groupedDemoClass
                          select groupedDemoClass).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Bu işe yarayacak !!!


198

Sadece mquander'ın önerisini somut hale getirmek için :

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .GroupBy(x => x.GroupKey)
                             .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Daha kısa değişken isimleri de kullanırsanız, tabii ki daha kısa yaparsınız :)

Ancak, bir Aramanın daha uygun olabileceğini önerebilir miyim ? Arama, temelde bir anahtardan diğerine bir sözlüktür IEnumerable<T>- değerlere bir liste olarak gerçekten ihtiyacınız olmadıkça , ToLookup çağrısıyla kodu daha da kısaltır (ve daha verimli) :

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .ToLookup(x => x.GroupKey);

1
Uzun vadeli bir ortamda bir aramanın, yerleşik bir sözlüğe kıyasla o kadar iyi performans göstermediğini düşündüm, çünkü her istek için sonucu taze oluşturuyor ... lütfen beni düzeltin, yanılıyorsam!
Andreas Niedermair

Hayır, tüm aramayı oluşturur. Genel olarak, ToXXX ertelenmiş yürütmeyi kullanmaz.
Jon Skeet

1
(Gerçekten ertelenmiş bir Gruplandırma düşünüyor olabilirsiniz.)
Jon Skeet

1
Bu kadar kinci olmasaydım, sana oy verirdim. Linq için geldi, hiç duymadığım veri yapısı için kaldı!
Chris McCall

2
@sasikt: Model, herhangi bir şeyi arayabilmeniz ve anahtar yoksa boş bir koleksiyon almanızdır . Bu genellikle TryGetValue yaklaşımı olan IMO'dan daha kullanışlıdır.
Jon Skeet

6

Zaten tek satırlık yaptın. ToDictionaryİlk satırınızın sonuna koyun . Daha kısa olmasını istiyorsanız, sorgu sözdizimi yerine işlevsel kompozisyon sözdizimini kullanın.


3

Burada biraz konu dışına çıkıyorum , ancak bu konuya girdim çünkü Linq'te bir sözlük sözlüğü oluşturmanın bir yolunu arıyordum ve buradaki konuşma beni cevaba yönlendiriyor ...

Sen olabilir size göre arama isterimki, 1'den fazla tuşuna veya boyut var senaryoları için yararlıdır çok düzeyli sözlükleri oluşturmak için linq kullanın. İşin püf noktası, bir gruplama oluşturmak ve ardından bunu aşağıdaki gibi bir sözlüğe dönüştürmektir:

  Dim qry = (From acs In ActualSales _
             Group By acs.ProductID Into Group _
             Select ProductID, Months = Group.ToDictionary(Function(c) c.Period) _
            ).ToDictionary(Function(c) c.ProductID)

Ortaya çıkan sorgu şu şekilde kullanılabilir:

 If qry.ContainsKey(_ProductID) Then
      With qry(_ProductID)
          If .Months.ContainsKey(_Period) Then
             ...
          End If
      End With
 End If

Umarım bu, bu tür bir sorguya ihtiyaç duyan herkes için yararlıdır.

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.