2011-01-18 30 views
3

リストは、次のようにプロパティを持つオブジェクトを持っている:List()から整数値の積算合計を取得するにはどうすればよいですか?

public class PropertyDetails 
{ 

public int Sequence { get; set; } 

public int Length { get; set; } 

public string Type { get; set; } 

public int Index { get; set; } 

} 

リストは順序を並べ替えられています。

配列= 1つの長= 20 TYPE = "" "インデックス= 0

配列= 2長= 8種類=" インデックス= 0

シーケンスを次のよう

リストオブジェクト値を有します= 3の長さ= 6種類= "" インデックス= 0

配列= 4長さ= 20 TYPE = "" インデックス= 0

配列= 5長さ= 8種類= "" インデックス= 0

は私が指数= 28

" "=インデックス= 20

シーケンス= 2長= 8タイプ" 私は

シーケンス= 1本の長さ= 20Type =" としてリストを結果として与えるLINQクエリをしたいです

配列= 3の長さ= 6種類= "インデックス= 62

""=" インデックス= 54

配列= 5長さ= 8種類 "インデックス= 34

配列= 4長さ= 20種類="

ここで、indexは、Lengthを考慮したシーケンスの累積合計です。

答えて

9

。むしろ、私はLINQがこの問題の間違った解決策であると感じています。従来のLINQ演算子には適していませんが、状態を操作する必要があります。

私はこれを行うだろう:

var sum = 0; 
foreach (var p in list) { 
    sum += p.Length; 
    p.Index = sum; 
} 

LINQがハンマーです。ハンマー・アドバイスを求めるのではなく、問題に適切なツールを使用していることを確認してください。

+0

あなたは* OPが状態を操作しようとしていると仮定しています。そうであれば、これは正しいアプローチです。もしそうでないなら、これはまったく適切ではありません。 LINQは、既存のオブジェクトを変更したい場合には適していないと言うのは間違いありません。それはあなたがより機能的なアプローチをしたい場合に最適なソリューションです。 OPが何をしようとしているかについて十分な情報がないことは残念です。 –

3

これを行う標準のLINQ演算子はありません。基本的には、実行中の集約が必要です。現時点では副作用のあるクエリを使用して偽装することはできますが、それだけです。

幸いにも、これを行う独自のクエリ演算子を簡単に作成できます。ような何か:

public static IEnumerable<TResult> Scan<TSource, TResult>(
    this IEnumerable<TSource> source, 
    TResult seed, 
    Func<TResult, TSource, TResult> func) 
{ 
    TResult current = seed; 
    // TODO: Argument validation 
    foreach (TSource item in source) 
    { 
     current = func(current, item); 
     yield return current; 
    } 
} 

次にあなたが使用することができます。

var query = list.Scan(new PropertyDetails(), 
         (current, item) => new PropertyDetails { 
          Sequence = item.Sequence, 
          Length = item.Length, 
          Index = current.Index + item.Length 
         }); 

編集:私は詳細をチェックしていないが、私は反応性拡張機能はそのSystem.Interactiveアセンブリ内の同様の方法を持っていると信じています。

+0

これは実際には使用していません。データベースはそれを効果的に処理することはできません。そして、それが "オブジェクトのためのLINQ"の場合は、私の質問は単に "なぜ"になりますか?新しい拡張メソッドを実装して、リスト内の各要素の新しいオブジェクトを作成します。さらに、単純なfor-loopで実行するよりも多くのコードを書く必要があります。 LINQはこれに適していません。 – Jakob

+0

@Jakob:集計を実行すると便利です。私はちょうど先日、1つを欲しかった。私はforeachループを書くのではなく、宣言的な方法でこの集約を表現することができます。私はまた、より大きなクエリの一部としてそれを使用できるようにしたい。 –

+0

私は、再利用できる一般的なソリューションを持つことが有益であるというあなたの推論に同意しますが、まずは実用的でなければならないと思います。この場合、ソリューション(つまり、第2コードブロック)を使用しても、Jakob全体よりもコードが多くなります。彼は読みやすく、理解しやすい。あなたのより一般的な解決方法は、複数の場所で使用する場合、コピーして貼り付けるよりも多くのコード行を生成することです。バグの数はコード行数に比例することがわかります。 – Theo

-2

多分これ(それは非常に読みやすいではありません)のようなもの:私はこれを言うんだろう決してけれども、私はジョンのソリューションは過剰性能であることがわかり

var newList = list.Select(x => 
         new PropertyDetails() 
         { 
          Type = x.Type, 
          Length = x.Length, 
          Sequence = x.Sequence, 
          Index = list.Take(x.Sequence).Select(y => y.Length).Aggregate((a, b) => a + b) 
         } 
); 
+2

驚くべきことに、この時間の複雑さは二次的です。 – Jakob

関連する問題