LINQ with groupby and count

To dość proste, ale jestem w rozsypce: Biorąc pod uwagę ten typ zbioru danych:

UserInfo(name, metric, day, other_metric)

I ten przykładowy zestaw danych:

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

Chciałbym pobrać tabelę, która wyświetla metryki w kolejności (0,1,2,3..) z całkowitą liczbą wystąpień. Więc z tego zestawu kończyłbyś:

0 3    
1 2    
2 2    
3 1

Zmagam się ze składnią LINQ, ale utknąłem na tym, gdzie umieścić groupby i liczyć.... jakaś pomoc??

Post Edit: nigdy nie byłem w stanie uzyskać zamieszczonych odpowiedzi do pracy, jak zawsze zwrócił jeden rekord z liczbą różnych liczeń. Jednak udało mi się złożyć przykład LINQ do SQL, który zadziałał:

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

Ten wynik dał mi uporządkowany zestaw rekordów z 'metrykami' i liczbą powiązanych z nimi użytkowników. Oczywiście jestem nowy w LINQ w ogóle i moim niewprawnym okiem to podejście wydaje się bardzo podobne do czystego podejścia LINQ jeszcze dał mi inną odpowiedź.

Author: wonea, 2011-09-02

3 answers

Po wywołaniu GroupBy, otrzymujesz serię grup IEnumerable<Grouping>, gdzie każda grupa ujawnia Key użyte do utworzenia grupy, a także IEnumerable<T> wszystkich elementów znajdujących się w oryginalnym zestawie danych. Musisz tylko zadzwonić Count() do tego ugrupowania, aby uzyskać subtotal.

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


To była genialnie szybka odpowiedź, ale mam mały problem z pierwszą linijką, a konkretnie " data.groupby (info= > info.metric) "

Zakładam, że już mieć listę / tablicę niektórych class, które wyglądają jak

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

Kiedy robisz data.GroupBy(x => x.metric), oznacza to: "dla każdego elementu {[11] } w ilości zdefiniowanej przez data Oblicz to .metric, następnie Grupuj wszystkie elementy z tą samą metryką w Grouping i zwróć IEnumerable wszystkich wynikowych grup. Biorąc pod uwagę przykładowy zestaw danych

    <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

Wynikałoby to z następującego wyniku po grupie:

(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]
 291
Author: Jimmy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-02 16:01:59

Zakładając, że userInfoList jest List<UserInfo>:

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

Funkcja lambda dla GroupBy(), n => n.metric oznacza, że otrzyma pole metric z każdego napotkanego obiektu UserInfo. Typ n jest zależny od kontekstu, w pierwszym wystąpieniu jest typu UserInfo, ponieważ lista zawiera obiekty UserInfo. W drugim wystąpieniu {[7] } jest typu Grouping, ponieważ teraz jest to lista obiektów Grouping.

Groupings mają metody rozszerzenia, takie jak .Count(), .Key() i prawie wszystko inne, co byś spodziewaj się. Tak jak można sprawdzić .Lenght na string, można sprawdzić .Count() na grupie.

 28
Author: Vladislav Zorov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-02 16:14:56
userInfos.GroupBy(userInfo => userInfo.metric)
        .OrderBy(group => group.Key)
        .Select(group => Tuple.Create(group.key, group.Count()));
 16
Author: DanielOfTaebl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-01 22:29:35