C#对象列表,如何获取属性的总和


158

我有一个对象列表。单个对象条目的一种属性是数量。我如何获得金额的总和?

如果我的列表是double类型的,则我可以执行以下操作:

double total = myList.Sum();

但是我想要类似的东西,但是这种语法是不正确的。

double total = myList.amount.Sum();

我应该如何去实现呢?我希望尽可能使用Sum函数,而不是循环遍历并计算值。

Answers:


310
using System.Linq;

...

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

12
这比foreach快要引起兴趣吗?
Coops

4
我也对@CodeBlend的问题感兴趣。这种计算会比for循环快吗?
rex 2014年

23
@Coops-要回答您的问题...使用包含100,000个对象的列表,每个对象具有一个数据类型为double的单个属性,使用上述解决方案(myList.Sum)将属性累加1000次需要2.44秒,而使用foreach则为0.98秒。使用秒表类测量经过时间的准确性。因此,foreach比使用myList.Sum快2倍以上。
Joe Gayetty

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
@Mason,对,这就是Alex在他先前的回答中解决问题的方式,所以我只是提供了一种不同的方法来做同样的事情。
有用蜜蜂

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(...)

对于第二项测试是:

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

看起来LINQ通常比foreach(...)慢,但是对我来说奇怪的是foreach(...)似乎比for循环快。


2
以供将来参考,看看StopwatchSystem.Diagnostics,因为它是一个高性能的时间记录。(顺便说一句,我没打败您)
Meirion Hughes

1
请勿DateTime.Now用于测量。它总是返回本地时间,因此性能很差。DateTime.UtcNow是比较快的; 但是,它仍然没有使用Stopwatch该类的高分辨率。
捷尔吉科塞格

3
这不能回答问题。
马克·帕蒂森

好的,谢谢小费。分数非常可重复,因此我认为这样的分辨率就足够了
Puchacz

2
尽管您的意图很好-马克说的很对-您没有明确回答问题。我建议您将其更改为:“这是您的操作方式”和“这是每个选项的CPU性能”。同样,原则上,如果您描述测试方法,则无需显示代码。
Meirion Hughes
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.