43
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LINQのAverage、Max、Min、Sumについて

Last updated at Posted at 2014-08-28

はじめに

 LINQ、超便利ですよね!LINQを使わず書いた6、7行のコードが、LINQを使うことで1行で書くことができます。とても簡潔に、そして読みやすくなりますよね。もう自分はLINQなしでC#のコードを書くのは考えられません。

 この投稿ではAverage、Max、Min、Sumメソッドを紹介します。

Average、Max、Min、Sumについて

 この投稿では今後、IEnumelable<T>のことをT型のシーケンスと呼びます。またこの投稿で、数値型とはint(Int32)、long(Int64)、float(Single)、double(Double)、decimal(Decimal)を指します。

 Average、Max、Min、Sumそれぞれのメソッドでできることは、そのメソッドの名前が表す通りのものです。

  • Average:シーケンスの平均値を求める
  • Max:シーケンスの最大値を求める
  • Min:シーケンスの最小値を求める
  • Sum:シーケンスの合計値を求める

 Average、Max、Min、Sumは非常に多くのオーバーロードを持っています。それぞれ各数値型のシーケンスに対してのオーバーロードがあります。また、Nullable<long>やNullable<double>のように各数値型のnull許容型のシーケンスのオーバーロードを持っています。

 またMaxとMinに関しては、intなどの数値型やそのnull許容型だけでなく、任意の型のシーケンスで呼び出すことが可能です。もしその型がIComparable<T>かIComparableを実装している場合、このメソッドはその実装を使用して値を比較した最大値・最小値を得ることが可能です。

 オーバーロードの数が非常に多いので、それぞれを個別に説明することはしません。

数値型と(そのnull許容型)のシーケンスの平均値、最大値、最小値、合計値を計算するもの

例えば次のようなコードです。

例(1)
double average = new List<int> {0, 1, 2, 3 }.Average (); // 1.5

int? max = new List<int?> {1, 4, 1, null, 4, 2, null, 3, 5, 6}.Max (); // 6

long min = new long[] {2, 2, 3, 4}.Min (); // 2

float sum = new float[] {3.0F ,1.0F, 4.0F, 1.0F, 5.0F, 9.0F, 2.0F}.Sum (); // 25.0F

 Average、Max、Min、Sumは、上記のように数値型のシーケンスの平均値、最大値、最小値、合計値を求めます。

変換関数を使って、変換した結果を計算するもの

 次のようなRecordClassを使います。

RecordClass
public class RecordClass
{
	public int Score { get; set; }
}

 引数に変換関数(デリゲート)を渡すオーバーロードです。次のコードではFunc<Record,int>を渡しています。recordListの各要素のScoreプロパティに対する平均値、最大値、最小値、合計値を求めています。

例(2)
List<RecordClass> recordClassList = GetRecordClassList ();
double average = recordClassList.Average (record => record.Score);
int max = recordClassList.Max (record => record.Score);
int min = recordClassList.Min (record => record.Score);
int sum = recordClassList.Sum (record => record.Score);

数値型以外のもの(MinとMax)

 数値型以外にも、MinとMaxは任意の型に対して呼び出すことが可能です。もしその型がIComparable<T>かIComparableを実装している場合、このメソッドはその実装を使用して値を比較した最大値・最小値を得ることが可能です。

 例を示します。

例(3)
List<string> jvmLanguages = new List<string> {
	"Java", "Scala", "Groovy", "Clojure", "JRuby", "Jython", "Kotlin", "Xtend", "Ceylon"
};
Debug.Log (jvmLanguages.Max()); // Xtend
Debug.Log (jvmLanguages.Min()); // Ceylon


TimeSpan[] timeSpans = new TimeSpan[] {
	new TimeSpan(1, 0, 0), new TimeSpan(0, 1, 0), new TimeSpan(0, 0, 1)
};
Debug.Log (timeSpans.Max ()); // 01:00:00
Debug.Log (timeSpans.Min ()); // 00:00:01

シーケンスが空の場合の各メソッドの挙動

Average

  • Average<int>などは、要素が空の場合、例外がスローされます。
  • Average<Nullable<int>>などは、シーケンスの要素が空かnull値のみを含む場合、nullを返します。

Funcを引数にとる場合、

  • Func<T, int>などを引数に取るものは要素が空の場合例外が発生します。
  • Func<T, Nullable<int>>などを引数にとるものは、ソースシーケンスが空かnull値のみを含む場合はnullを返します。

MaxとMin

  • Max<TSource>はTSourceが参照型で、シーケンスが空かnull値のみを含む場合、nullを返します。

  • Max<TSource>はTSourceが値型で、シーケンスが空の場合、例外をスローします。

  • Max<int>などはシーケンスが空の場合、例外をスローします。

  • Max<Nullable<int>>などはシーケンスが空もしくはnull値のみを含む場合、nullを返します。

Minも同様です。

Sum

  • Sum<int>などは要素が含まれない場合は0を返します。
  • Sum<Nullable<int>>などは要素が含まれない場合0を返します。

※ Func系を引数にとるものも同じで0を返します。
※ Nullblle系の返り値型は、Nullable<int>型で、nullでなく0値を持っているもの。

MSDNへのリンク

 MSDNへのリンクを下記に示します。

まとめ

 LINQの中でも、Average、Max、Min、Sumは、理解しやすく、使いやすく、利用できそうな場面が多いですよね。

補足

 MinやMaxなどこの投稿でとりあげたLINQメソッドは、以前のUnityでは問題がありました。いくつかの条件を満たしてしまった場合、AOTコンパイラの不具合により、iOSなどAOTコンパイルが必要なプラットフォームで実行時例外が発生したのです。

 現在Unityでは、かつてAOTコンパイルが行われていたプラットフォームで、IL2CPPという技術が使われています。

 私が把握している限り、IL2CPPでは本投稿で紹介したメソッドは、問題なく使えているようです。そのため本投稿の記事タイトルを変更し、内容も各メソッドの紹介のみとしました。

 過去の内容を見たい場合は、編集履歴よりご覧ください。

43
44
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?