C # Список объектов, как я могу получить сумму имущества


158

У меня есть список объектов. Одним из свойств отдельной записи объекта является сумма. Как мне получить сумму?

Если мой список был типа 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

4
Меня также интересует вопрос @ CodeBlend. Будет ли это вычисление быстрее, чем цикл for?
Рекс

23
@Coops - чтобы ответить на ваш вопрос ... используя список, содержащий 100 000 объектов, каждый объект, имеющий одно свойство типа данных double, суммируя свойство 1000 раз, используя решение выше (myList.Sum), занимает 2,44 секунды по сравнению с 0,98 секундами с использованием foreach. , Истекшее время измеряется с помощью класса секундомера для точности. Следовательно, foreach более чем в 2 раза быстрее, чем myList.Sum.
Джо Гайетти

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
@ Мейсон, верно, и именно так Алекс подошел к проблеме в своем предыдущем ответе, поэтому я просто предложил другой способ сделать то же самое.
полезноBee

1
Ах да, извините за мое заблуждение.
Мейсон

Я ценю, что это уникальный ответ, но производительность не пострадает?
Питер Ленджо

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 (...) выглядит быстрее, чем для цикла.


2
для справки в будущем, посмотрим на Stopwatchв , System.Diagnosticsтак как это время рекордер высокой производительности. (Между прочим, я не отрицал вас)
Мейрион Хьюз

1
Не используйте DateTime.Nowдля измерения. У него ужасная производительность, так как он всегда возвращает местное время. DateTime.UtcNowбыстрее; однако, он все еще не использует такое высокое разрешение, как Stopwatchкласс.
Дьёрдь Кёсег

3
Это не отвечает на вопрос.
Марк Паттисон

Хорошо, спасибо за совет. Счет очень повторяемый, поэтому я предположил, что такого разрешения достаточно
Puchacz

2
Хотя ваше намерение хорошее, Марк прав, вы не отвечаете на вопрос в явном виде. Я бы порекомендовал вам изменить его на: «Вот как вы могли бы это сделать» и «Вот производительность процессора каждого варианта». Также в принципе, если вы описываете свою методологию тестирования, вам не нужно показывать нам код.
Мейрион Хьюз
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.