2012-03-17 18 views
2

Listの一般的な拡張メソッドを書く必要があります.List(T)の各文字列プロパティを条件付きで考慮し、条件が満たされた場合にTの対応するdecimalプロパティを合計します。これまでの私の努力:任意の指導のためのExtensionメソッド、SumIf for generic List <T>

// foreach(p in Persons) { if(p.Name == "mort"){sum p.Amount;} } 

public static double SumIf<T>(this T o, List<T> ListItems, 
      string targetStr, ?strVals?, ?dblVals?) 
{ 
    double sum = 0; 
    foreach(T item in ListItems) 
    { 
     if(item.?strVal? == targetStr){ sum += item.?dblVal? ; } 
    } 
    return sum; 
} 

おかげで、 MORT

+0

上記の方法はあなたを与えるん何が問題? –

+0

['Aggregate'](http://msdn.microsoft.com/library/system.linq.enumerable.aggregate.aspx)は機能しませんか?または['Where'](http://msdn.microsoft.com/library/system.linq.enumerable.where.aspx)に続いて[' Sum'](http://msdn.microsoft.com/library/system .linq.enumerable.sum.aspx)?または、ヘルパー拡張メソッドが必要ですか? – BACON

答えて

4

あなたは、文字列プロパティと二重のプロパティを抽出する方法をしたいようですが、(あなたのポストで「小数」はあったと仮定して聞こえます)あなたのコード内で「ダブル」のではなく、タイプミス - Funcはここに適切である:

public static double SumIf<T>(this IEnumerable<T> source, 
      string targetText, 
      Func<T, string> textSelector, 
      Func<T, double> valueSelector) 
{ 
    double sum = 0; 
    foreach (T item in source) 
    { 
     if (textSelector(item) == targetText) 
     { 
      sum += valueSelector(item); 
     } 
    } 
    return sum; 
} 

(私は未使用の初期パラメータを削除したことに注意してください、そしてそれを、リスト自体の拡張メソッドを作っ使用していません。価値はabのように感じる私には臭いのそれあなたが本当にリストであることを、それを必要としないよう...私はまたIEnumerable<T>にパラメータの種類を変更した)

(注)この実際には、ほとんど同等のものに:。

public static double SumIf<T>(this IEnumerable<T> source, 
      string targetText, 
      Func<T, string> textSelector, 
      Func<T, double> valueSelector) 
{ 
    return source.Where(x => textSelector(x) == targetText) 
       .Sum(valueSelector); 
} 
私は個人的にはおそらく代わりに、文字列とテキストセレクタの一般的な述語関数のために行くだろう

public static double SumIf<T>(this IEnumerable<T> source, 
      Func<T, bool> predicate, 
      Func<T, double> valueSelector) 
{ 
    return source.Where(predicate) 
       .Sum(valueSelector); 
} 

次に、あなたは

double sum = list.SumIf(x => x.Name == "mort", x => x.Amount); 
とそれを呼びたいです

double sum = list.SumIf("mort", x => x.Name, x => x.Amount); 

...しかし、かなり柔軟です:として私には同じように良いようだ

...。

コメントに記載されているとおり、これは本当に必要ですか?単純なWhere/Sum呼び出しを耐え難いほどにするために十分な場所で使用していますか?あなたは、それは、例えば、一般的なことができないことをそれを作るあなたの方法にいくつかの非常に特定の制約を導入

double sum = list.Sum(x => x.Name == "mort" ? x => x.Amount : 0d); 
+0

2番目の実装でSelectを呼び出してリストタイプを文字列に変更したため、Tのリストに対してSumを呼び出すことができなかった点を除いて、すべてが良いです。 – 000

+0

@Sam:Doh、本当にありがとう。 –

+0

ありがとうございます – 000

0

:ヘック、あなたは条件演算子を使用してちょうどSum呼び出しに変換することができますTには金額が必要です。これは、関数などでこれらの依存関係を渡す方が良いでしょう:

public static double SumIf<T>(this IList<T> source, 
           Func<T, bool> pred, 
           Func<T, double> val) 
{ 
    double sum = 0; 
    foreach (var item in source) 
     if (pred(item)) 
      sum += val(item); 

    return sum; 
} 

次に、あなただけのラムダとしてあなたの述語との和プロパティセレクタに渡すことができます。

List<Person> people = new List<Person>(); 
people.Add(new Person() { Name = "Joe", Amount =20.2}); 
people.Add(new Person() { Name = "Fred", Amount = 11 }); 
people.Add(new Person() { Name = "Joe", Amount = 5.7 }); 

double sum = people.SumIf(x => x.Name == "Joe", x => x.Amount);