C#のLINQの関数であるAverage()
の使い方についてです。
配列やリストなどのシーケンス内の要素の平均値を求めることが出来ます。
この記事には.NET Framework 4.6.1を使用しています。
先生「先日の小テストの平均点は62点でした。」
学生時代を思い出しますね。
平均点という概念は、学生のとき学びました。
全員の点数を足して、人数で割れば求められるアレです。
プログラムでも平均値を出す機会はあるかもしれません。
そんなときはLINQのAverage()
を使ってやってください。
小数点型の要素の平均を取得する
小数の型を扱う、decimal
型、double
型、float
型の平均値を求めるときは簡単です。
各型の要素の配列やリストに対してAverage()
を呼んであげることで平均値は求められます。
public static decimal Average( this IEnumerable<decimal> source )
Enumerable.Average メソッド (IEnumerable(Decimal)) (System.Linq)
public static double Average( this IEnumerable<double> source )
Enumerable.Average メソッド (IEnumerable(Double)) (System.Linq)
public static float Average( this IEnumerable<float> source )
Enumerable.Average メソッド (IEnumerable(Single)) (System.Linq)
Program.cs
using System.Linq; using System.Collections; using System.Collections.Generic; public static class Program { static void Main( string[] args ) { // 数値データ。 float[] floatNumbers = new float[] { 1.0f, 3.0f, 6.0f }; double[] doubleNumbers = new double[] { 1.0d, 3.0d, 6.0d }; decimal[] decimalNumbers = new decimal[] { 1.0m, 3.0m, 6.0m }; float floatAverage = floatNumbers.Average(); double doubleAverage = doubleNumbers.Average(); decimal decimalAverage = decimalNumbers.Average(); // 結果発表 System.Console.WriteLine( "floatNumbers:{0}", floatNumbers.Text() ); System.Console.WriteLine( "平均:{0}", floatAverage ); System.Console.WriteLine( "doubleNumbers:{0}", doubleNumbers.Text() ); System.Console.WriteLine( "平均:{0}", doubleAverage ); System.Console.WriteLine( "decimalNumbers:{0}", decimalNumbers.Text() ); System.Console.WriteLine( "平均:{0}", decimalAverage ); // 入力待ち用 System.Console.ReadKey(); } /// <summary> /// 簡易的なシーケンスのテキスト取得処理 /// </summary> public static string Text( this IEnumerable i_source ) { string text = string.Empty; foreach( var value in i_source ) { text += string.Format( "[{0}], ", value ); } return text; } } // class Program
floatNumbers:[1], [3], [6],
平均:3.333333
doubleNumbers:[1], [3], [6],
平均:3.33333333333333
decimalNumbers:[1.0], [3.0], [6.0],
平均:3.3333333333333333333333333333
整数型の要素の平均を取得する
整数型である、int
型、long
型でもAverage()
を使って平均値を求められます。
ですが平均値は整数で表せないことが多いため、返り値はdouble
型になっている点に注意が必要です。
public static double Average( this IEnumerable<int> source )
Enumerable.Average メソッド (IEnumerable(Int32)) (System.Linq)
public static double Average( this IEnumerable<long> source )
Enumerable.Average メソッド (IEnumerable(Int64)) (System.Linq)
Program.cs
using System.Linq; using System.Collections; using System.Collections.Generic; public static class Program { static void Main( string[] args ) { // 数値データ。 int[] intNumbers = new int[] { 1, 2, 3, 4 }; long[] longNumbers = new long[] { 1, 2, 3, 4 }; // 整数型の場合は、double型で平均が求められる double intAverage = intNumbers.Average(); double longAverage = longNumbers.Average(); // 結果発表 System.Console.WriteLine( "intNumbers:{0}", intNumbers.Text() ); System.Console.WriteLine( "平均:{0}", intAverage ); System.Console.WriteLine( "longNumbers:{0}", longNumbers.Text() ); System.Console.WriteLine( "平均:{0}", longAverage ); // 入力待ち用 System.Console.ReadKey(); } /// <summary> /// 簡易的なシーケンスのテキスト取得処理 /// </summary> public static string Text( this IEnumerable i_source ) { string text = string.Empty; foreach( var value in i_source ) { text += string.Format( "[{0}], ", value ); } return text; } } // class Program
intNumbers:[1], [2], [3], [4],
平均:2.5
longNumbers:[1], [2], [3], [4],
平均:2.5
Null許容型の要素の平均を取得する
上記の各型のNull許容型にもAverage()
は対応しています。
public static decimal? Average( this IEnumerable<decimal?> source )
Enumerable.Average メソッド (IEnumerable(Nullable(Decimal))) (System.Linq)
public static double? Average( this IEnumerable<double?> source )
Enumerable.Average メソッド (IEnumerable(Nullable(Double))) (System.Linq)
public static float? Average( this IEnumerable<float?> source )
Enumerable.Average メソッド (IEnumerable(Nullable(Single))) (System.Linq)
public static double? Average( this IEnumerable<int?> source )
Enumerable.Average メソッド (IEnumerable(Nullable(Int32))) (System.Linq)
public static double? Average( this IEnumerable<long?> source )
Enumerable.Average メソッド (IEnumerable(Nullable(Int64))) (System.Linq)
Program.cs
using System.Linq; using System.Collections; using System.Collections.Generic; public static class Program { static void Main( string[] args ) { // 数値データ。 int?[] intNumbers = new int?[] { 1, 2, 3, 4, null }; long?[] longNumbers = new long?[] { null, null, null, null, null }; // 整数型の場合は、double型で平均が求められる double? intAverage = intNumbers.Average(); double? longAverage = longNumbers.Average(); // 結果発表 System.Console.WriteLine( "intNumbers:{0}", intNumbers.Text() ); System.Console.WriteLine( "平均:{0}", intAverage ); System.Console.WriteLine( "longNumbers:{0}", longNumbers.Text() ); System.Console.WriteLine( "平均:{0}", longAverage ); // 入力待ち用 System.Console.ReadKey(); } /// <summary> /// 簡易的なシーケンスのテキスト取得処理 /// </summary> public static string Text( this IEnumerable i_source ) { string text = string.Empty; foreach( var value in i_source ) { text += string.Format( "[{0}], ", value ); } return text; } } // class Program
intNumbers:[1], [2], [3], [4], ,
平均:2.5
longNumbers:, , , , ,
平均:
ここでNull許容型でAverage()
を使った際の特徴として、以下の点が挙げられます
- 要素が全て
Null
だった場合、Null
が返される - 要素が
Null
のものは、平均値を出す際の要素の数としてはみなさない
(上記の例のintNumbersでは、
要素数:5 合計:10 平均:2 ではなく、
要素数:4 合計:10 平均:2.5 と扱っている)
それ以外の型の場合を取得する
ではそれ以外の型の平均値を求める場合はどうすればいいでしょうか。
その場合は、Average()
の第二引数に平均値を求める値を返す処理を記述することで求めることが出来ます。
public static decimal Average<TSource>( this IEnumerable<TSource> source, Func<TSource, decimal> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Decimal)) (System.Linq)
public static double Average<TSource>( this IEnumerable<TSource> source, Func<TSource, double> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Double)) (System.Linq)
public static float Average<TSource>( this IEnumerable<TSource> source, Func<TSource, float> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Single)) (System.Linq)
public static double Average<TSource>( this IEnumerable<TSource> source, Func<TSource, int> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Int32)) (System.Linq)
public static double Average<TSource>( this IEnumerable<TSource> source, Func<TSource, long> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Int64)) (System.Linq)
以下の例ではラムダ式を用いて、自作クラス内の平均を求めたいプロパティを渡す処理を記述しています。
Program.cs
using System.Linq; using System.Collections; using System.Collections.Generic; public static class Program { private class Parameter { public string Name { get; set; } public int Age { get; set; } public override string ToString() { return string.Format( "Name:{0}, Age:{1}", Name, Age ); } } static void Main( string[] args ) { // 年齢と名前データ。 Parameter[] parameters = new Parameter[] { new Parameter() { Age = 52, Name = "正一郎" }, new Parameter() { Age = 28, Name = "清次郎" }, new Parameter() { Age = 20, Name = "誠三郎" }, new Parameter() { Age = 18, Name = "征史郎" }, }; // 整数型の場合は、double型で平均が求められる double average = parameters.Average( value => value.Age ); // 結果発表 System.Console.WriteLine( "parameters:{0}", parameters.Text() ); System.Console.WriteLine( "年齢の平均:{0}", average ); // 入力待ち用 System.Console.ReadKey(); } /// <summary> /// 簡易的なシーケンスのテキスト取得処理 /// </summary> public static string Text( this IEnumerable i_source ) { string text = string.Empty; foreach( var value in i_source ) { text += string.Format( "[{0}], ", value ); } return text; } } // class Program
parameters:[Name:正一郎, Age:52], [Name:清次郎, Age:28], [Name:誠三郎, Age:20],
[Name:征史郎, Age:18],
年齢の平均:29.5
この方式の場合も、Null許容型が対応しています。
public static decimal? Average<TSource>( this IEnumerable<TSource> source, Func<TSource, decimal?> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Nullable(Decimal))) (System.Linq)
public static double? Average<TSource>( this IEnumerable<TSource> source, Func<TSource, double?> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Nullable(Double))) (System.Linq)
public static float? Average<TSource>( this IEnumerable<TSource> source, Func<TSource, float?> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Nullable(Single))) (System.Linq)
public static double? Average<TSource>( this IEnumerable<TSource> source, Func<TSource, int?> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Nullable(Int32))) (System.Linq)
public static double? Average<TSource>( this IEnumerable<TSource> source, Func<TSource, long?> selector )
Enumerable.Average(TSource) メソッド (IEnumerable(TSource), Func(TSource, Nullable(Int64))) (System.Linq)
Average()
を七兆回使って、いろいろな平均値を出してみてください。
LINQのリンク
LINQ一覧
www.urablog.xyzMax
シーケンス(配列やリスト)内の最大値の要素を求めたい!
www.urablog.xyzMin
シーケンス(配列やリスト)内の最小値の要素を求めたい!
www.urablog.xyzSum
シーケンス(配列やリスト)内の要素の合計値を求めたい!
www.urablog.xyz