Groupby ve count ile LINQ


222

Bu oldukça basit ama ben bir kayıp: Bu tür bir veri kümesi göz önüne alındığında:

UserInfo(name, metric, day, other_metric)

ve bu örnek veri kümesi:

joe  1 01/01/2011 5
jane 0 01/02/2011 9
john 2 01/03/2011 0
jim  3 01/04/2011 1
jean 1 01/05/2011 3
jill 2 01/06/2011 5
jeb  0 01/07/2011 3
jenn 0 01/08/2011 7

Toplam sayımın gerçekleşme sırasına göre metrikleri (0,1,2,3 ..) sırayla listeleyen bir tablo almak istiyorum. Yani bu setten:

0 3    
1 2    
2 2    
3 1

LINQ sözdizimi ile boğuşuyorum ama nerede bir groupby koymak ve .... herhangi bir yardım koymak sıkışmış?

POST Edit: Her zaman farklı sayılarla bir kayıt döndürdüğü için gönderilen cevapları hiçbir zaman çalıştıramadım. Ancak ben bir LINQ SQL örneği işe koydum başardı:

        var pl = from r in info
                 orderby r.metric    
                 group r by r.metric into grp
                 select new { key = grp.Key, cnt = grp.Count()};

Bu sonuç bana 'metriklerle' sıralı bir kayıt kümesi ve her biriyle ilişkili kullanıcı sayısını verdi. Genel olarak LINQ için yeniyim ve eğitimsiz gözüm için bu yaklaşım saf LINQ yaklaşımına çok benziyor ama bana farklı bir cevap verdi.


Evet, ama jimmy'nin açıklaması bana daha çok yardımcı oldu. Ancak onun örneğini asla çalıştıramadım ama bu beni yeni bir yöne yönlendirdi.
Gio

@Jimmy, standart LINQ sorgu sözdizimi yerine LINQ ifadeleri için işlevsel sözdizimini kullandı ve ayrıca gecikmiş yürütme biçimi yerine bu işlevlerin hemen yürütülmesini göstermeye karar verdi. Kafa karıştırıcı yeni bir kişi için. Bunu neden yaptığını bilmiyorum.
Richard Robertson

Yanıtlar:


396

Aradıktan sonra GroupBy, IEnumerable<Grouping>her Gruplamanın kendisinin Keygrubu oluşturmak için kullanılanları açığa çıkardığı ve ayrıca IEnumerable<T>orijinal veri kümenizdeki öğelerden biri olduğu bir dizi grup alırsınız . Count()Ara toplamı almak için bu Gruplamayı aramanız yeterlidir.

foreach(var line in data.GroupBy(info => info.metric)
                        .Select(group => new { 
                             Metric = group.Key, 
                             Count = group.Count() 
                        })
                        .OrderBy(x => x.Metric)
{
     Console.WriteLine("{0} {1}", line.Metric, line.Count);
}


Bu çok hızlı bir yanıttı ama ilk satırda, özellikle "data.groupby (info => info.metric)" ile ilgili bir sorun yaşıyorum

Zaten classbenzeyen bazı listeleriniz / dizileriniz olduğunu varsayıyorum

class UserInfo {
    string name;
    int metric;
    ..etc..
} 
...
List<UserInfo> data = ..... ;

Bunu yaptığınızda data.GroupBy(x => x.metric), "ile xtanımlanan IEnumerable'daki her öğe için databunu hesaplayın .metric, ardından aynı metriğe sahip tüm öğeleri Groupingbir IEnumerablegrupta gruplayın ve elde edilen tüm gruplardan birini döndürün.

    <DATA>           | Grouping Key (x=>x.metric) |
joe  1 01/01/2011 5  | 1
jane 0 01/02/2011 9  | 0
john 2 01/03/2011 0  | 2
jim  3 01/04/2011 1  | 3
jean 1 01/05/2011 3  | 1
jill 2 01/06/2011 5  | 2
jeb  0 01/07/2011 3  | 0
jenn 0 01/08/2011 7  | 0

groupby'den sonra şu sonuca neden olur:

(Group 1): [joe  1 01/01/2011 5, jean 1 01/05/2011 3]
(Group 0): [jane 0 01/02/2011 9, jeb  0 01/07/2011 3, jenn 0 01/08/2011 7]
(Group 2): [john 2 01/03/2011 0, jill 2 01/06/2011 5]
(Group 3): [jim  3 01/04/2011 1]

Bu çok hızlı bir cevaptı ama ilk satırda, özellikle "data.groupby (info => info.metric)" ile ilgili bir sorun yaşıyorum. Açıkça 'veri' şu anda veri kümesidir, ancak 'info.metric' neyi temsil eder? tanımı nedir?
Gio

"info.metric", sorunuzda bahsettiğiniz UserInfo sınıfındaki metrik özellik / alan olacaktır.
lee-m

1
Teşekkürler anladım ama aslında bu bana tek bir değer veriyor gibi görünüyor - yani farklı metrik sayılarının toplam sayısı. Bu örnekte bana kaç farklı sayım olduğunu gösteren "metrik 4" ifadesini alıyorum.
Gio

1
Vay. Tamamen gruplama açıkladı !! Bu yalnız yazı değdi .... ben stil "metrikleri 4" sonucu almak ama teşekkürler!
Gio

4
Bu cevabın başlangıcında, "GroupBy'yi çağırdıktan sonra, her bir Gruplamanın kendisi grubu oluşturmak için kullanılan Anahtarı açığa çıkardığı ve aynı zamanda orijinal verilerinizdeki öğelerin IEnumerable <T> olduğu bir dizi IEnumerable <Grouping> grubuna sahip olursunuz. set ", LINQ Group'un en açık açıklamasıdır Henüz okuduğum için teşekkürler.
dumbledad

48

Varsayarsak userInfoListbir olduğunu List<UserInfo>:

        var groups = userInfoList
            .GroupBy(n => n.metric)
            .Select(n => new
            {
                MetricName = n.Key,
                MetricCount = n.Count()
            }
            )
            .OrderBy(n => n.MetricName);

Lambda işlevi GroupBy(), karşılaşılan her nesneden n => n.metricalan alacağı anlamına gelir . Türü nesneye göre değişir, ilk sırada türdür , çünkü liste nesneleri içerir . İkinci durumda tür , çünkü şimdi nesnelerin bir listesi .metricUserInfonUserInfoUserInfonGroupingGrouping

Groupings uzantısı gibi yöntemleri var .Count(), .Key()ve beklediğiniz başka hemen hemen hiçbir şey. Eğer kontrol gibi sadece .Lenghtbir üzerine stringkontrol edebilirsiniz .Count()bir grup.


23
userInfos.GroupBy(userInfo => userInfo.metric)
        .OrderBy(group => group.Key)
        .Select(group => Tuple.Create(group.Key, group.Count()));

1
küçük yazım hatası -> group.keySelect (...) olmalıdırgroup.Key
Jan
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.