C # Перелік об'єктів, як отримати суму властивості


158

У мене є список об’єктів. Одна властивість окремого запису об'єкта - це сума. Як отримати суму суми?

Якщо мій список був подвійним, я можу зробити щось подібне:

double total = myList.Sum();

Однак я хочу щось подібне до цього, але цей синтаксис є неправильним.

double total = myList.amount.Sum();

Як я повинен іти до досягнення цього? Я хотів би використовувати функцію Sum, якщо можливо, замість того, щоб переглядати та обчислювати значення.

Відповіді:


310
using System.Linq;

...

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

12
Це швидше, ніж пропонувати з інтересу?
Чашки

4
Мене також цікавить питання @ CodeBlend. Чи буде це обчислення швидше, ніж для циклу?
рекс

23
@Coops - щоб відповісти на ваше запитання ... використовуючи список, що містить 100 000 об'єктів, кожен об'єкт має одну властивість типу даних подвійний, підсумовуючи властивість в 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
@ Мейсон, правда, саме так Олексій підійшов до проблеми у своїй попередній відповіді, тому я просто запропонував інший спосіб зробити те саме.
корисноБе

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.