コレクションの要素数を数える
C#で配列やリストなどのコレクションを扱う際、そこに「データが何件あるか」を知ることは最も基本的な操作の一つです。
配列には.Lengthプロパティ、List<T>には.Countプロパティがありますが、LINQ(Language Integrated Query)のCount()メソッドを使用すると、あらゆるコレクション(IEnumerable<T>)に対して統一的な方法で要素数を取得できます。さらに、特定の条件を満たす要素だけをフィルタリングして数えることも可能です。
この記事では、Countメソッドの基本的な使い方と、条件付きでのカウント、そしてパフォーマンスに関する注意点について解説します。
1. 全要素数を取得する
引数を指定せずにCount()メソッドを呼び出すと、シーケンスに含まれるすべての要素数をint型で返します。
コード例:配列の要素数
単純な整数の配列に含まれるデータの個数を取得する例です。
using System;
using System.Linq; // LINQを使用するために必須
public class CountBasicExample
{
public static void Main()
{
// センサーから取得した温度データの配列
double[] temperatures = { 24.5, 25.1, 23.8, 26.0, 24.2, 25.5 };
// 配列内の全データの個数を取得
int totalCount = temperatures.Count();
Console.WriteLine($"データ件数: {totalCount}");
}
}
出力結果:
データ件数: 6
2. 条件に一致する要素数を取得する
Countメソッドの真価は、引数に**条件式(述語)**を渡せる点にあります。これにより、「Whereで絞り込んでからCountする」という2段階の処理を、1つのメソッドで簡潔に記述できます。
構文: int Count(Func<T, bool> predicate)
コード例:条件付きカウント
注文データのリストから、「未発送(IsShippedがfalse)」かつ「注文額が一定以上」の件数をカウントする例です。
using System;
using System.Collections.Generic;
using System.Linq;
// 注文データを表すクラス
public class Order
{
public int OrderId { get; set; }
public decimal TotalAmount { get; set; }
public bool IsShipped { get; set; }
}
public class CountConditionalExample
{
public static void Main()
{
var orderList = new List<Order>
{
new Order { OrderId = 101, TotalAmount = 5000, IsShipped = true },
new Order { OrderId = 102, TotalAmount = 12000, IsShipped = false },
new Order { OrderId = 103, TotalAmount = 3000, IsShipped = false },
new Order { OrderId = 104, TotalAmount = 15000, IsShipped = true },
new Order { OrderId = 105, TotalAmount = 8000, IsShipped = false }
};
// 条件: 未発送 (IsShipped == false) かつ 金額が 5000円 以上
int priorityOrders = orderList.Count(x => !x.IsShipped && x.TotalAmount >= 5000);
Console.WriteLine($"優先対応が必要な注文数: {priorityOrders}");
}
}
出力結果:
優先対応が必要な注文数: 2
(ID 102 と ID 105 が条件に該当します)
プロパティ(Length / Count)との違いとパフォーマンス
配列やList<T>には、LINQメソッドではない独自のプロパティが存在します。
- 配列:
Lengthプロパティ List<T>:Countプロパティ
単純に「全要素数」を知りたいだけであれば、LINQのCount()メソッドよりも、これらのプロパティを使用する方がパフォーマンスが優れています。
- プロパティ (
.Length,.Count): 内部で保持している値を返すだけなので、計算量は O(1)(一瞬)です。 - LINQメソッド (
.Count()): 汎用的なIEnumerable<T>に対して動作するため、場合によってはシーケンスを最初から最後まで走査する必要があり、計算量が O(N)(要素数に比例)になることがあります。 (注: LINQの実装では、対象がICollectionなどを実装している場合は最適化されプロパティを参照しますが、明示的にプロパティを使った方が意図が明確になります。)
使い分けの指針:
- 配列やリストの「全件」を知りたい場合 → プロパティ (
.Length,.Count) - 条件付きで数えたい場合、または型が
IEnumerable<T>の場合 → LINQメソッド (.Count(...))
補足:LongCount
Countメソッドはint型を返しますが、もし要素数がintの最大値(約21億)を超えるような巨大なデータを扱う場合は、**LongCount**メソッドを使用します。使い方はCountと同じで、戻り値がlong型になります。
long hugeCount = data.LongCount(x => x.IsValid);
まとめ
Count(): シーケンスの全要素数を取得します。Count(predicate): 条件に一致する要素数を取得します。Where(...).Count()と書くよりも簡潔です。- パフォーマンス: 配列やリストの全件数を取得する場合は、可能な限り
.Lengthや.Countプロパティを使用することが推奨されます。
