207

I have a list of objects. One property of the individual object entry is amount. How do I get the sum of amount?

If my list was of type double I may be able to do something like this:

double total = myList.Sum();

However I want to something similar to this, yet this syntax is incorrect.

double total = myList.amount.Sum();

How should I go about accomplishing this? I would love to use the Sum function if possible instead of looping through and calculating the value.

Cheng Chen
  • 42,509
  • 16
  • 113
  • 174
Joseph U.
  • 4,457
  • 10
  • 41
  • 47

4 Answers4

395
using System.Linq;

...

double total = myList.Sum(item => item.Amount);
Paul C
  • 4,687
  • 5
  • 39
  • 55
Alex LE
  • 20,042
  • 4
  • 30
  • 28
  • 14
    Is this quicker than foreach out of interest? – Paul C Feb 04 '13 at 14:08
  • 4
    I am also interested in @CodeBlend's question. Will this computation be faster than a for loop? – rex Feb 25 '14 at 11:29
  • 33
    @Coops - To answer your question...using a list containing 100,000 objects, each object having a single property of datatype double, summing up the property 1,000 times using solution above (myList.Sum) takes 2.44 seconds compared to 0.98 seconds using foreach. The elapsed time is measured using the Stopwatch class for accuracy. Therefore foreach is over 2x faster than using myList.Sum. – Joe Gayetty Nov 11 '16 at 15:23
  • 4
    Linq is never quicker than pure foreach. Use it only in convenient, non-time-critical places. – Vitalii Vasylenko Oct 25 '20 at 14:26
53

And if you need to do it on items that match a specific condition...

double total = myList.Where(item => item.Name == "Eggs").Sum(item => item.Amount);
Greg Quinn
  • 1,927
  • 1
  • 23
  • 26
15

Another alternative:

myPlanetsList.Select(i => i.Moons).Sum();
usefulBee
  • 9,250
  • 10
  • 51
  • 89
5

Here is example code you could run to make such test:

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);

The same example for complex object is:

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; }
}

My results with compiler optimizations off are:

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

and for second test are:

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

it looks like LINQ is generally slower than foreach(...) but what is weird for me is that foreach(...) appears to be faster than for loop.

Puchacz
  • 1,987
  • 2
  • 24
  • 38
  • 2
    for future reference, have a look at `Stopwatch` in `System.Diagnostics` as it is a high-performance time recorder. (I didn't downvote you btw) – Meirion Hughes Feb 19 '16 at 09:50
  • 1
    Do not use `DateTime.Now` for measuring. It has terrible performance as it returns always local time. `DateTime.UtcNow` is faster; however, it still does not use as high resolution as the `Stopwatch` class. – György Kőszeg Feb 19 '16 at 09:54
  • 3
    This does not answer the question. – Mark Pattison Feb 19 '16 at 09:57
  • Ok, thanks for tip. Score's are very repeatable so I assumed that such resolution is enough – Puchacz Feb 19 '16 at 09:58
  • 2
    While your intention is good -Mark is right- you're not explicitly answering the question. I'd recommend you change it to: "Here is how you could do it" and "Here is the cpu performance of each option". Also in principle if you describe your testing methodology you need-not show us the code. – Meirion Hughes Feb 19 '16 at 10:08
  • "but what is weird for me is that foreach(...) appears to be faster than for loop." Its not indexing an array, its enumerating along a list, lists use pointers to the next item. – Andy Morris Feb 19 '16 at 10:22
  • @AndyMorris Firstly, he's using arrays. Secondly, [lists use arrays internally](http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs). Thirdly, the times are not accurate because of the use of DateTime.Now. As the answer currently is, it both does not answer the question and has meaningless tests and results. – kjbartel Feb 21 '16 at 05:20