Saya punya kelas, seperti ini:
public class MyClass
{
public int Value { get; set; }
public bool IsValid { get; set; }
}
Sebenarnya itu jauh lebih besar, tetapi ini menciptakan kembali masalah (keanehan).
Saya ingin mendapatkan jumlah dari Value
, di mana instance itu valid. Sejauh ini, saya telah menemukan dua solusi untuk ini.
Yang pertama adalah ini:
int result = myCollection.Where(mc => mc.IsValid).Select(mc => mc.Value).Sum();
Namun, yang kedua adalah ini:
int result = myCollection.Select(mc => mc.IsValid ? mc.Value : 0).Sum();
Saya ingin mendapatkan metode yang paling efisien. Saya, pada awalnya, berpikir bahwa yang kedua akan lebih efisien. Kemudian bagian teoretis saya mulai berjalan "Ya, satu adalah O (n + m + m), yang lain adalah O (n + n). Yang pertama harus bekerja lebih baik dengan lebih banyak cacat, sedangkan yang kedua harus berkinerja lebih baik dengan kurang ". Saya pikir mereka akan tampil setara. EDIT: Dan kemudian @Martin menunjukkan bahwa Di mana dan Pilih digabungkan, jadi itu seharusnya benar-benar O (m + n). Namun, jika Anda melihat di bawah, sepertinya ini tidak terkait.
Jadi saya mengujinya.
(Lebih dari 100 baris, jadi saya pikir lebih baik mempostingnya sebagai Intisari.)
Hasilnya ... menarik.
Dengan toleransi dasi 0%:
Timbangan ini mendukung Select
dan Where
, sekitar ~ 30 poin.
How much do you want to be the disambiguation percentage?
0
Starting benchmarking.
Ties: 0
Where + Select: 65
Select: 36
Dengan toleransi dasi 2%:
Itu sama, kecuali bahwa untuk beberapa mereka berada dalam 2%. Saya akan mengatakan itu margin kesalahan minimum. Select
dan Where
sekarang hanya memiliki ~ 20 poin.
How much do you want to be the disambiguation percentage?
2
Starting benchmarking.
Ties: 6
Where + Select: 58
Select: 37
Dengan toleransi dasi 5%:
Inilah yang saya katakan sebagai margin of error maksimum saya. Itu membuatnya sedikit lebih baik untuk Select
, tetapi tidak banyak.
How much do you want to be the disambiguation percentage?
5
Starting benchmarking.
Ties: 17
Where + Select: 53
Select: 31
Dengan toleransi dasi 10%:
Ini jalan keluar dari batas kesalahan saya, tetapi saya masih tertarik dengan hasilnya. Karena itu memberi Select
dan Where
dua puluh poin memimpin itu untuk sementara waktu sekarang.
How much do you want to be the disambiguation percentage?
10
Starting benchmarking.
Ties: 36
Where + Select: 44
Select: 21
Dengan toleransi dasi 25%:
Ini cara, jalan keluar dari batas kesalahan saya, tetapi saya masih tertarik dengan hasilnya, karena Select
dan Where
masih (hampir) mempertahankan keunggulan 20 poin mereka. Sepertinya itu mengungguli dalam beberapa yang berbeda, dan itulah yang memberinya keunggulan.
How much do you want to be the disambiguation percentage?
25
Starting benchmarking.
Ties: 85
Where + Select: 16
Select: 0
Sekarang, aku menebak bahwa memimpin 20 poin berasal dari tengah-tengah, di mana mereka berdua terikat untuk mendapatkan sekitar kinerja yang sama. Saya bisa mencoba dan mencatatnya, tetapi itu akan menjadi seluruh informasi untuk diterima. Grafik akan lebih baik, saya kira.
Jadi itulah yang saya lakukan.
Ini menunjukkan bahwa Select
garis tetap stabil (diharapkan) dan Select + Where
garis naik (diharapkan). Namun, apa yang membingungkan saya adalah mengapa itu tidak sesuai dengan Select
pada 50 atau lebih awal: sebenarnya saya mengharapkan lebih awal dari 50, karena pencacah ekstra harus dibuat untuk Select
dan Where
. Maksud saya, ini menunjukkan 20 poin memimpin, tetapi itu tidak menjelaskan mengapa. Ini, saya kira, adalah poin utama dari pertanyaan saya.
Kenapa berperilaku seperti ini? Haruskah saya mempercayainya? Jika tidak, haruskah saya menggunakan yang lain atau yang ini?
Seperti @KingKong disebutkan dalam komentar, Anda juga dapat menggunakan Sum
kelebihan yang membutuhkan lambda. Jadi dua opsi saya sekarang diubah menjadi ini:
Pertama:
int result = myCollection.Where(mc => mc.IsValid).Sum(mc => mc.Value);
Kedua:
int result = myCollection.Sum(mc => mc.IsValid ? mc.Value : 0);
Saya akan membuatnya sedikit lebih pendek, tetapi:
How much do you want to be the disambiguation percentage?
0
Starting benchmarking.
Ties: 0
Where: 60
Sum: 41
How much do you want to be the disambiguation percentage?
2
Starting benchmarking.
Ties: 8
Where: 55
Sum: 38
How much do you want to be the disambiguation percentage?
5
Starting benchmarking.
Ties: 21
Where: 49
Sum: 31
How much do you want to be the disambiguation percentage?
10
Starting benchmarking.
Ties: 39
Where: 41
Sum: 21
How much do you want to be the disambiguation percentage?
25
Starting benchmarking.
Ties: 85
Where: 16
Sum: 0
Keunggulan dua puluh poin masih ada, artinya itu tidak ada hubungannya dengan Where
dan Select
kombinasi yang ditunjukkan oleh @Marcin dalam komentar.
Terima kasih telah membaca dinding teks saya! Juga, jika Anda tertarik, ini versi modifikasi yang mencatat CSV yang digunakan Excel.
Where
+ Select
tidak menyebabkan dua iterasi terpisah pada pengumpulan input. LINQ untuk Objek mengoptimalkannya menjadi satu iterasi. Baca Lebih Lanjut di posting blog
mc.Value
.