2013-06-07 16 views
5

私はいくつかの列を含むデータテーブルを持っています。 私は、グループ化せずに、LINQでこれらの平均値を計算したい: 私はこれを試してみました:グループ化せずにlinqで平均を計算する

dtPointCollFb.GroupBy(r => 1).Select(r => new 
     { 
      Plus100 = r.Average(item => item.PLUS100), 
      Plus50 = r.Average(item => item.PLUS50), 
      Plus10 = r.Average(item => item.PLUS10), 
      Plus5 = r.Average(item => item.PLUS5), 
      Plus1 = r.Average(item => item.PLUS1), 
      NULLA = r.Average(item => item.NULLA) 
     }).ToList() 

これは私が合計を計算する際に、完璧に動作しますが、平均的には最初のレコードの値を生成し、いないすべてのレコードの平均。 これは不要です:.GroupBy(r => 1)私は定数でグループ化しているためです。

しかし、これなしで、私はちょうど全体のクエリのための、そして唯一の列の平均使用することはできません。

dtPointCollFb.Average(r => r.PLUS100) 

だから、誰かが簡単なベストプラクティスソリューションを作り出すことができますか? メソッドの構文で可能な場合は、クエリではありません。

dtPointCollFb.GroupBy(r => 0).Select(r => new 
     { 
      Plus100 = r.Sum(item => item.PLUS100)/dtPointCollFb.Rows.Count, 
      Plus50 = r.Sum(item => item.PLUS50)/dtPointCollFb.Rows.Count, 
      Plus10 = r.Sum(item => item.PLUS10)/dtPointCollFb.Rows.Count, 
      Plus5 = r.Sum(item => item.PLUS5)/dtPointCollFb.Rows.Count, 
      Plus1 = r.Sum(item => item.PLUS1)/dtPointCollFb.Rows.Count, 
      NULLA = r.Sum(item => item.NULLA)/dtPointCollFb.Rows.Count 
     }).ToList() 

が、簡単かつきれいな方法で:

は、私はこのような何かをしたいです。これにより、平均値が正しく生成されます。

+0

同じではありませんが、別々に平均を計算することをお勧めします。 – speti43

+0

レコードの場合、 'GroupBy'構造は、データベースへの1回のラウンドトリップですべての平均を計算することを意図しています。 – Rawling

+0

はい、あなたは正しいです、私はSQLサーバーから多くのデータを転送するため、これが最善の方法です。このパターンは、linqを使用してWebサーバー上で複数の集約を行うように設計されています。私は同じデータ収集から異なるものを計算します。私は5つの異なるSQLクエリでそれを行うことができます。私は知らないかもしれませんが、おそらくそれは良いでしょう。 – speti43

答えて

6

Enumerable.Averageは、一連の数値の平均を計算します。したがって、必要な平均値ごとに列を投影する必要があります(つまり、Select)。

dtPointCollFb.Select(r => r.PLUS100).Average() 

または

dtPointCollFb.Average(r => r.PLUS100)  

GroupByリストのリストを作成します。この場合、(外側の)リストには1つの要素があります。 (あなたが任意に元のリスト内のすべての要素のために同じ鍵を使用しているので)

だからあなたは上記の持っている同じように簡単のように書くことができるか:

var averages = new 
{ 
    Plus100 = dtPointCollFb.Average(item => item.PLUS100), 
    Plus50 = dtPointCollFb.Average(item => item.PLUS50), 
    Plus10 = dtPointCollFb.Average(item => item.PLUS10), 
    Plus5 = dtPointCollFb.Average(item => item.PLUS5), 
    Plus1 = dtPointCollFb.Average(item => item.PLUS1), 
    NULLA = dtPointCollFb.Average(item => item.NULLA) 
}; 

より多くの何もして、カスタマイズが必要となります拡張機能(IEnumerable<DataTableClass>を拡張)。

+0

ニースの解決策:) – speti43

2

クリストファーが示唆したように、拡張機能を使用する場合は、Aggregateメソッドを使用できます。

public static DataPoint Average(this IEnumerable<DataPoint> dataPoints) 
{ 
    var count = 0; 
    var totals = dataPoints.Aggregate((lhs, rhs) => 
     { 
      ++count; 
      return new DataPoint 
       { 
        Plus100 = lhs.Plus100 + rhs.Plus100, 
        Plus50 = lhs.Plus50 + rhs.Plus50, 
        Plus10 = lhs.Plus10 + rhs.Plus10, 
        Plus5 = lhs.Plus5 + rhs.Plus5, 
        Plus1 = lhs.Plus1 + rhs.Plus1, 
        NULLA = lhs.NULLA + rhs.NULLA 
       }; 
     }); 

    return new DataPoint 
     { 
      Plus100 = totals.Plus100/count, 
      Plus50 = totals.Plus50/count, 
      Plus10 = totals.Plus10/count, 
      Plus5 = totals.Plus5/count, 
      Plus1 = totals.Plus1/count, 
      NULLA = totals.NULLA/count 
     }; 
} 

この方法の利点は、それが唯一行くことである:平均化機能は、この(手動カウントは、コレクションを介して複数の列挙を避ける)ようになり、クラス

public class DataPoint 
{ 
    public double Plus100 { get; set; } 
    public double Plus50 { get; set; } 
    public double Plus10 { get; set; } 
    public double Plus5 { get; set; } 
    public double Plus1 { get; set; } 
    public double NULLA { get; set; } 
} 

考える

一度コレクションを通して。大規模なデータセットをお持ちの場合、これにより計算能力が節約されます。データポイントが少ない場合は、私はChristopherの方法を使用します。

+0

良い提案、私はあなたのように作ったが、私はlinq拡張メソッドを作っていない。しかし、私もネストされたクラスを作りました。ありがとう! – speti43

関連する問題