ฉันมีชั้นเรียนเช่นนี้
public class MyClass
{
public int Value { get; set; }
public bool IsValid { get; set; }
}
อันที่จริงแล้วมันมีขนาดใหญ่กว่า แต่สิ่งนี้ทำให้เกิดปัญหาขึ้นอีกครั้ง
ฉันต้องการได้ผลรวมของValue
ซึ่งเป็นกรณีที่ถูกต้อง จนถึงตอนนี้ฉันได้พบสองวิธีนี้
คนแรกคือ:
int result = myCollection.Where(mc => mc.IsValid).Select(mc => mc.Value).Sum();
อย่างไรก็ตามอันที่สองคือ:
int result = myCollection.Select(mc => mc.IsValid ? mc.Value : 0).Sum();
ฉันต้องการวิธีที่มีประสิทธิภาพที่สุด ตอนแรกฉันคิดว่าอันที่สองจะมีประสิทธิภาพมากกว่า จากนั้นส่วนทางทฤษฎีของฉันเริ่มไป "อืม, อันหนึ่งคือ O (n + m + m), อีกอันหนึ่งคือ O (n + n). อันแรกควรทำงานได้ดีกว่าโดยมี invalids มากกว่า, ในขณะที่อันที่สองควรทำงานได้ดีขึ้น มีน้อย " ฉันคิดว่าพวกเขาจะแสดงอย่างเท่าเทียมกัน แก้ไข: และจากนั้น @Martin ชี้ให้เห็นว่า Where และ the Select รวมกันดังนั้นจึงควรเป็น O (m + n) อย่างไรก็ตามหากคุณดูด้านล่างดูเหมือนว่าสิ่งนี้จะไม่เกี่ยวข้องกัน
ดังนั้นฉันจึงนำไปทดสอบ
(มันมีมากกว่า 100 บรรทัดดังนั้นฉันคิดว่ามันจะดีกว่าถ้าจะโพสต์เป็นส่วนสำคัญ)
ผลลัพธ์เป็น ... น่าสนใจ
ด้วยความอดทนเสมอ 0%:
ตาชั่งอยู่ในความโปรดปรานของSelect
และWhere
ประมาณ ~ 30 คะแนน
How much do you want to be the disambiguation percentage?
0
Starting benchmarking.
Ties: 0
Where + Select: 65
Select: 36
ด้วยความอดทนผูก 2%:
มันเหมือนกันยกเว้นบางอย่างที่พวกเขาอยู่ภายใน 2% ฉันจะบอกว่านั่นเป็นข้อผิดพลาดขั้นต่ำ Select
และWhere
ตอนนี้มีเพียงตะกั่ว ~ 20 แต้ม
How much do you want to be the disambiguation percentage?
2
Starting benchmarking.
Ties: 6
Where + Select: 58
Select: 37
ด้วยความอดทน 5% ผูก:
นี่คือสิ่งที่ฉันจะบอกว่าเป็นข้อผิดพลาดสูงสุดของฉัน มันทำให้ดีขึ้นเล็กน้อยสำหรับSelect
แต่ไม่มาก
How much do you want to be the disambiguation percentage?
5
Starting benchmarking.
Ties: 17
Where + Select: 53
Select: 31
ด้วยความอดทนผูก 10%:
นี่เป็นข้อผิดพลาดเล็กน้อย แต่ฉันยังคงสนใจในผลลัพธ์ เพราะมันให้Select
และWhere
ตะกั่วยี่สิบจุดมันมีอยู่พักหนึ่งแล้ว
How much do you want to be the disambiguation percentage?
10
Starting benchmarking.
Ties: 36
Where + Select: 44
Select: 21
ด้วยความอดทน 25% ผูก:
นี่คือวิธีวิธีออกจากอัตรากำไรขั้นต้นของฉันของข้อผิดพลาด แต่ฉันยังคงอยู่ในความสนใจผลที่เพราะSelect
และWhere
ยังคง (เกือบ) เพื่อให้นำ 20 จุดของพวกเขา ดูเหมือนว่ามันจะดีกว่าในบางส่วนและนั่นคือสิ่งที่ทำให้มันเป็นผู้นำ
How much do you want to be the disambiguation percentage?
25
Starting benchmarking.
Ties: 85
Where + Select: 16
Select: 0
ตอนนี้ผมคาดเดาว่านำ 20 จุดมาจากตรงกลางที่พวกเขาทั้งสองที่ถูกผูกไว้ที่จะได้รับรอบผลการดำเนินงานเดียวกัน ฉันสามารถลองและบันทึกมันได้ แต่มันจะเป็นการโหลดข้อมูลทั้งหมดที่จะเข้ามากราฟจะดีกว่าฉันเดา
นั่นคือสิ่งที่ฉันทำ
มันแสดงให้เห็นว่าSelect
เส้นคงที่ (คาดว่า) และSelect + Where
เส้นปีนขึ้น (คาดว่า) แต่สิ่งที่ฉันปริศนาคือเหตุผลที่มันไม่ตรงกับSelect
ที่ 50 หรือก่อนหน้า: ในความเป็นจริงผมคาดหวังว่าก่อนหน้านี้กว่า 50, แจงนับเป็นพิเศษจะต้องมีการสร้างขึ้นสำหรับและSelect
Where
ฉันหมายความว่าสิ่งนี้แสดงให้เห็นถึงจุดนำ 20 จุด แต่มันไม่ได้อธิบายว่าทำไม นี่ฉันเดาว่าเป็นประเด็นหลักของคำถามของฉัน
ทำไมมันมีพฤติกรรมเช่นนี้? ฉันควรไว้ใจหรือไม่ ถ้าไม่ฉันควรใช้อันอื่นหรืออันนี้
ตามที่ @KongKong พูดถึงในความคิดเห็นคุณสามารถใช้Sum
เกินของแลมบ์ดา ดังนั้นสองทางเลือกของฉันตอนนี้เปลี่ยนเป็น:
ครั้งแรก:
int result = myCollection.Where(mc => mc.IsValid).Sum(mc => mc.Value);
ประการที่สอง:
int result = myCollection.Sum(mc => mc.IsValid ? mc.Value : 0);
ฉันจะทำให้มันสั้นลงเล็กน้อย แต่:
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
จุดนำยี่สิบจุดยังคงอยู่ที่นั่นซึ่งหมายความว่าไม่จำเป็นต้องเกี่ยวข้องกับWhere
และการSelect
รวมกันที่ @Marcin ชี้ให้เห็นในความคิดเห็น
ขอบคุณที่อ่านข้อความของฉัน! นอกจากนี้หากคุณสนใจนี่คือรุ่นที่ปรับเปลี่ยนแล้วซึ่งจะบันทึก CSV ที่ Excel ใช้
Where
+ Select
ไม่ทำให้เกิดการวนซ้ำสองครั้งที่แยกกันระหว่างการรวบรวมอินพุต LINQ to Objects ปรับมันให้เป็นหนึ่งซ้ำ อ่านเพิ่มเติมในโพสต์บล็อก
mc.Value
มี