グループ化して上位N件ずつ取得

似たような事を既に書いてるけど、懲りずに。

■やりたいこと:
テーブル(コレクション)TからGでグルーピングしてOで並べ替えて、グループ毎の上位N件ずつだけ取得。

T-SQLだとこんな感じか。

SELECT *
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY G ORDER BY O) rn
    FROM T) x
WHERE rn <= N


LINQ to Objects だとこう

T.GroupBy(x => x.G).Select(x => x.OrderBy(y => y.O).Take(N)).SelectMany(x => x);


メソッド化

public static IEnumerable<T> TopPerGroup<T, TGroupKey, TOrderKey>(
    this IEnumerable<T> source,
    Func<T, TGroupKey> groupKeySelector,
    Func<T, TOrderKey> orderKeySelector,
    int count)
{
    return source
        .GroupBy(groupSelector)
        .Select(x => x.OrderBy(orderKeySelector).Take(count))
        .SelectMany(x => x);
}


使い方

T.TopPerGroup(x => x.G, x => x.O, N);