C#オブジェクトのリスト、プロパティの合計を取得する方法


158

オブジェクトのリストがあります。個々のオブジェクトエントリの1つのプロパティは金額です。金額の合計を取得するにはどうすればよいですか?

私のリストがdouble型だった場合、次のようなことができるかもしれません。

double total = myList.Sum();

しかし、私はこれに似たものにしたいのですが、この構文は正しくありません。

double total = myList.amount.Sum();

これを達成するにはどうすればよいですか?ループして値を計算するのではなく、可能であればSum関数を使用したいと思います。

回答:


310
using System.Linq;

...

double total = myList.Sum(item => item.Amount);

12
これは、関心のないforeachよりも速いですか?
Coops 2013

4
@CodeBlendの質問にも興味があります。この計算はforループよりも高速ですか?
レックス2014

23
@Coops-質問に答えるために... 100,000個のオブジェクトを含むリストを使用し、各オブジェクトはデータ型doubleの単一プロパティを持ち、上記のソリューション(myList.Sum)を使用してプロパティを1,000回合計すると、foreachを使用する0.98秒に比べて2.44秒かかります。 。経過時間は、精度を高めるためにストップウォッチクラスを使用して測定されます。したがって、foreachはmyList.Sumを使用するよりも2倍以上高速です。
Joe Gayetty、2016

36

そして、特定の条件に一致するアイテムでそれを行う必要がある場合...

double total = myList.Where(item => item.Name == "Eggs").Sum(item => item.Amount);

11

別の選択肢:

myPlanetsList.Select(i => i.Moons).Sum();

5
代わりに.Select(i => i.Moons).Sum()使用できます.Sum(i => i.Moons)
メイソン

1
@メイソン、そう、それがアレックスが彼の以前の答えで問題に取り組んだ方法なので、私は同じことをする別の方法を提供しました。
有用なビー

1
ああ、そうだ、誤解してすみません。
メイソン、

これはユニークな答えだと思いますが、パフォーマンスは低下しませんか?
Peter Lenjo

2

このようなテストを行うために実行できるコードの例を次に示します。

var f = 10000000;
var p = new int[f];

for(int i = 0; i < f; ++i)
{
    p[i] = i % 2;
}

var time = DateTime.Now;
p.Sum();
Console.WriteLine(DateTime.Now - time);

int x = 0;
time = DateTime.Now;
foreach(var item in p){
   x += item;
}
Console.WriteLine(DateTime.Now - time);

x = 0;
time = DateTime.Now;
for(int i = 0, j = f; i < j; ++i){
   x += p[i];
}
Console.WriteLine(DateTime.Now - time);

複雑なオブジェクトの同じ例は次のとおりです。

void Main()
{
    var f = 10000000;
    var p = new Test[f];

    for(int i = 0; i < f; ++i)
    {
        p[i] = new Test();
        p[i].Property = i % 2;
    }

    var time = DateTime.Now;
    p.Sum(k => k.Property);
    Console.WriteLine(DateTime.Now - time);

    int x = 0;
    time = DateTime.Now;
    foreach(var item in p){
        x += item.Property;
    }
    Console.WriteLine(DateTime.Now - time);

    x = 0;
    time = DateTime.Now;
    for(int i = 0, j = f; i < j; ++i){
        x += p[i].Property;
    }
    Console.WriteLine(DateTime.Now - time);
}

class Test
{
    public int Property { get; set; }
}

コンパイラの最適化をオフにした私の結果は次のとおりです。

00:00:00.0570370 : Sum()
00:00:00.0250180 : Foreach()
00:00:00.0430272 : For(...)

2番目のテストは次のとおりです。

00:00:00.1450955 : Sum()
00:00:00.0650430 : Foreach()
00:00:00.0690510 : For()

LINQは一般にforeach(...)より遅いようですが、私にとって奇妙なのは、foreach(...)がforループよりも高速に見えることです。


2
将来の参考のために、見ていStopwatchSystem.Diagnostics、それは高性能なタイムレコーダーであるように。(私はあなたに反対票を投じませんでした)
Hughes

1
DateTime.Now測定には使用しないでください。それは常に現地時間を返すので、それはひどいパフォーマンスを持っています。DateTime.UtcNow高速です。ただし、それでもStopwatchクラスほどの高解像度は使用されません。
ジェルジKőszeg

3
これは質問の答えにはなりません。
Mark Pattison、2016

ヒント、ありがとう。スコアは非常に再現性が高いので、そのような解像度で十分だと
思いました

2
あなたの意図は良いですが、マークは正しいですが、あなたは質問に明確に答えていません。「これがどのように実行できるか」と「各オプションのCPUパフォーマンスはここです」に変更することをお勧めします。また、原則として、テスト方法を説明する場合は、コードを示す必要はありません。
Meirion Hughes 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.