言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

C#辞典

  1. トップページ
  2. C#辞典
  3. Enumerable.Count() / Sum() / Average()

Enumerable.Count() / Sum() / Average()

対応: C# 3.0(2007)

シーケンスの件数・合計・平均・最大・最小を集計する LINQ の拡張メソッドです。

構文

using System.Linq;

int    count = source.Count();
int    count2 = source.Count(x => 条件);
long   longCnt = source.LongCount();

int    sum = source.Sum();
double avg = source.Average();
T      max = source.Max();
T      min = source.Min();

// セレクターを渡して変換後の値を集計することもできます。
int    sumKey = source.Sum(x => x.Price);
double avgKey = source.Average(x => x.Score);

メソッド一覧

メソッド概要
Count()シーケンスの要素数を返します。
Count(predicate)条件に一致する要素の数を返します。
LongCount()要素数を『long』型で返します(大規模データ向け)。
Sum(selector)数値要素(または変換後の値)の合計を返します。
Average(selector)数値要素の平均を返します。シーケンスが空の場合は例外を投げます。
Max()最大値を返します。
Max(selector)変換後の値の最大値を返します。
Min()最小値を返します。
Min(selector)変換後の値の最小値を返します。
MaxBy(keySelector).NET 6 以降。最大キーを持つ要素そのものを返します。
MinBy(keySelector).NET 6 以降。最小キーを持つ要素そのものを返します。

サンプルコード

Program.cs
using System;
using System.Collections.Generic;
using System.Linq;

List<int> scores = new List<int> { 80, 95, 70, 88, 60, 92 };

// 基本的な集計
Console.WriteLine(scores.Count()); // 6
Console.WriteLine(scores.Sum()); // 485
Console.WriteLine(scores.Average()); // 80.833...
Console.WriteLine(scores.Max()); // 95
Console.WriteLine(scores.Min()); // 60

// 条件付き件数(80 点以上の人数)
Console.WriteLine(scores.Count(s => s >= 80)); // 4

// オブジェクトのリストでセレクターを使って集計します。
var products = new List<(string Name, int Price, int Qty)>
{
    ("りんご", 150, 3),
    ("みかん", 80, 5),
    ("バナナ", 120, 2),
};
Console.WriteLine(products.Sum(p => p.Price * p.Qty)); // 1090 — 売上合計
Console.WriteLine(products.Average(p => p.Price)); // 116.666... — 平均価格
Console.WriteLine(products.Max(p => p.Price)); // 150 — 最高価格

// .NET 6 以降: MaxBy で最高価格の商品オブジェクトを取得します。
var mostExpensive = products.MaxBy(p => p.Price);
Console.WriteLine(mostExpensive.Name); // りんご

// グループごとに集計します。
var grouped = scores.GroupBy(s => s >= 80 ? "合格" : "不合格");
foreach (var g in grouped)
    Console.WriteLine($"{g.Key}: {g.Count()}人, 平均 {g.Average():F1}点");

コンパイルして実行すると次のようになります。

dotnet run
6
485
80.8333333333333
95
60
4
1090
116.666666666667
150
りんご
合格: 4人, 平均 88.8点
不合格: 2人, 平均 65.0点

よくあるミス

よくあるミス: Average() は空のシーケンスで例外を投げる

Average() はシーケンスが空の場合に InvalidOperationException をスローします。空の可能性がある場合は、Any() で確認してから呼び出すか、DefaultIfEmpty() でデフォルト値を挿入してください。

using System;
using System.Collections.Generic;
using System.Linq;

// NG: 空のシーケンスで Average() を呼ぶ
List<int> empty = new List<int>();
// double avg = empty.Average(); // InvalidOperationException: Sequence contains no elements.

修正後は次の通りです。

using System;
using System.Collections.Generic;
using System.Linq;

// OK: Any() で空チェックしてから呼ぶ
List<int> empty = new List<int>();
double avg1 = empty.Any() ? empty.Average() : 0.0;
Console.WriteLine(avg1); // 0

// OK: DefaultIfEmpty() でデフォルト値を挿入してから平均を取る
double avg2 = empty.DefaultIfEmpty(0).Average();
Console.WriteLine(avg2); // 0

修正後は次の通りです。

dotnet run
0
0

概要

『Sum()』『Average()』などは即時評価で動作し、メソッドを呼んだ時点でシーケンス全体を走査します。これらを連続して呼び出すと走査も複数回行われるため、大規模データでは事前にリスト化しておくと効率的です。

『Average()』はシーケンスが空の場合に『InvalidOperationException』を投げます。空の可能性がある場合はあらかじめ『Any()』で確認するか、『DefaultIfEmpty()』と組み合わせてください。

条件に合う要素の有無だけを調べたい場合は、『Count(predicate) > 0』よりも『Enumerable.Any(predicate)』の方が効率的です。グループごとの集計には『Enumerable.GroupBy()』を組み合わせて使います。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。