- PR -

メソッドの記述方法

1
投稿者投稿内容
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2009-02-14 15:38
 配列に対して統計のメジアン(中央値)を返すメソッドを作成しています。Average()の外観と同じにしたいため、ソースコード1のような外観を持つメソッドにすることに決めました。また、計算ロジックは汎用性を持たせたいと考えました。

 その結果、ソースコード2ができましたが、あらゆる型に対応しようとすると型の数だけ冗長な拡張メソッドを作成しなければならないのが不満です。
良い解決策があればアドバイス願います。

// ****** ソースコード1 *****

using System;
using Personal.Generic;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
int[] test = { 10, 100, 20, 30, 140 };
// 統計のメジアン(中央値)を計算します。
// 配列を対象に下記の外観を持つメソッドを設計したい。
//
// Average = 60 Median = 30 が出力されます
Console.WriteLine("Average = {0} Median = {1}", test.Average() , test.Median());

}
}
}

// ***** ソースコード2 *****

using System;

namespace Personal.Generic
{
// 汎用のメジアン(非公開版)
internal sealed class Median<T> where T : IComparable
{
// 計算ロジック
internal static T DoCalcurate(T[] source)
{
// 対象が破壊されるのを防ぐため複製します。
T[] temp = source.Clone() as T[];
// 並べ替えます。
Array.Sort<T>(temp);
// 中央の要素を返します。
return temp[temp.Length / 2];
}
}

// 公開版メジアン(LINQ風)
public static class MethodLib
{
// int版
public static int Median(this int[] input)
{
return Median<int>.DoCalcurate(input);
}
// float版
public static float Median(this float[] input)
{
return Median<float>.DoCalcurate(input);
}
// double版
public static double Median(this double[] input)
{
return Median<double>.DoCalcurate(input);
}
}
}
otf
ベテラン
会議室デビュー日: 2006/08/04
投稿数: 91
投稿日時: 2009-02-14 23:04
コード:
    public static class Statistics
    {
        public static T Median<T>(this IEnumerable<T> source)
        {
            return source.OrderBy(_ => _).ElementAt(source.Count() / 2);
        }
    }



これでどうでしょうか?
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2009-02-15 10:45
コード:
public static T Median<T>(this T[] input) where T : IComparable 
{
    return Median<T>.DoCalcurate(input);
}



元の形を活かして、こんな感じにするのも手です。

IEnumerable<T>を対象にすると非常に柔軟にできるのですが、
処理速度に明確な差が出てくるので悩みどころですね。

#提示のデータ例のパターンでも結構な差がでます。
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2009-02-16 11:17
ご回答ありがとうございます。
Genericクラスにしたのが間違いでした。
最初からGenericメソッドにするべきでした。
パフォーマンスも考慮して下記の方法にしました。

public static T Median<T>(this T[] input) where T : IComparable
{
T[] temp = input.Clone() as T[];
Array.Sort<T>(temp);
return temp[temp.Length / 2];
}


本題とは外れますが、
私は配列を複写する時、よくClone()を使いますが、
冗長な型検査(as T[])が発生してしまいます。
1行増えますが、やはりArray.Copyにするべきですね。細かいことですが...
T[] temp = new T[input.Length];
Array.Copy(input,temp,temp.Length);



1

スキルアップ/キャリアアップ(JOB@IT)