C # Daftar objek, bagaimana cara mendapatkan jumlah properti

158

Saya punya daftar objek. Salah satu properti dari entri objek individu adalah jumlah. Bagaimana saya mendapatkan jumlah jumlahnya?

Jika daftar saya bertipe double, saya mungkin dapat melakukan sesuatu seperti ini:

double total = myList.Sum();

Namun saya ingin sesuatu yang mirip dengan ini, namun sintaks ini salah.

double total = myList.amount.Sum();

Bagaimana saya harus menyelesaikan ini? Saya ingin menggunakan fungsi Sum jika memungkinkan alih-alih mengulang dan menghitung nilainya.

Joseph U.
sumber

Jawaban:

310
using System.Linq;

...

double total = myList.Sum(item => item.Amount);
Alex LE
sumber
12
Apakah ini lebih cepat dari sebelumnya karena minat?
Coops
4
Saya juga tertarik dengan pertanyaan @ CodeBlend. Apakah perhitungan ini akan lebih cepat daripada for for?
rex
23
@Coops - Untuk menjawab pertanyaan Anda ... menggunakan daftar yang berisi 100.000 objek, masing-masing objek memiliki properti tunggal ganda tipe data, meringkas properti 1.000 kali menggunakan solusi di atas (myList.Sum) membutuhkan 2,44 detik dibandingkan dengan 0,98 detik menggunakan foreach . Waktu yang berlalu diukur menggunakan kelas Stopwatch untuk akurasi. Karena itu foreach lebih dari 2x lebih cepat daripada menggunakan myList.Sum.
Joe Gayetty
36

Dan jika Anda perlu melakukannya pada item yang cocok dengan kondisi tertentu ...

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

Alternatif lain:

myPlanetsList.Select(i => i.Moons).Sum();
BermanfaatBee
sumber
5
Alih-alih .Select(i => i.Moons).Sum()Anda dapat menggunakan.Sum(i => i.Moons)
Mason
1
@Mason, benar dan itulah bagaimana Alex mendekati masalah dalam jawaban sebelumnya, jadi saya hanya menyediakan cara berbeda untuk melakukan hal yang sama.
bermanfaatBee
1
Ah ya, maaf atas kesalahpahaman saya.
Mason
Saya menghargai bahwa ini adalah jawaban yang unik, tetapi tidakkah kinerja akan menurun?
Peter Lenjo
2

Berikut adalah contoh kode yang dapat Anda jalankan untuk melakukan tes seperti itu:

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

Contoh yang sama untuk objek kompleks adalah:

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

Hasil saya dengan optimasi penyusun tidak aktif adalah:

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

dan untuk tes kedua adalah:

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

sepertinya LINQ umumnya lebih lambat daripada foreach (...) tetapi yang aneh bagi saya adalah bahwa foreach (...) tampaknya lebih cepat daripada for loop.

Puchacz
sumber
2
untuk referensi di masa mendatang, kita lihat Stopwatchdi System.Diagnosticskarena merupakan kinerja tinggi perekam waktu. (Saya tidak menyuarakannya btw)
Meirion Hughes
1
Jangan gunakan DateTime.Nowuntuk mengukur. Ini memiliki kinerja yang mengerikan karena selalu mengembalikan waktu setempat. DateTime.UtcNowlebih cepat; Namun, masih tidak menggunakan resolusi setinggi Stopwatchkelas.
György Kőszeg
3
Ini tidak menjawab pertanyaan.
Mark Pattison
Ok, terima kasih atas tipnya. Skornya sangat berulang sehingga saya berasumsi bahwa resolusi seperti itu sudah cukup
Puchacz
2
Meskipun niat Anda baik -Mark benar- Anda tidak secara eksplisit menjawab pertanyaan itu. Saya sarankan Anda mengubahnya ke: "Ini adalah bagaimana Anda bisa melakukannya" dan "Ini adalah kinerja cpu dari setiap opsi". Juga pada prinsipnya jika Anda mendeskripsikan metodologi pengujian Anda, Anda tidak perlu menunjukkan kode pada kami.
Meirion Hughes