LINQ ที่ไหนเทียบกับในขณะเดียวกัน


99

ฉันต้องการทราบความแตกต่างระหว่างวิธีการTakeWhile& WhereLINQ ฉันได้รับข้อมูลต่อไปนี้จาก MSDN แต่มันไม่สมเหตุสมผลสำหรับฉัน

Where<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>) 

กรองลำดับของค่าตามเพรดิเคต

TakeWhile<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>)

ส่งคืนองค์ประกอบจากลำดับตราบเท่าที่เงื่อนไขที่ระบุเป็นจริง

ยินดีรับฟังทุกความคิดเห็น


1
คำถามที่ดี - Intellisense บน TakeWhile ยังคงระบุว่า "ส่งคืนองค์ประกอบ ... ตราบเท่าที่เงื่อนไขที่ระบุเป็นจริง" สิ่งนี้สามารถตีความได้เป็นอย่างดีว่าเป็น Where ข้อความควรเป็นอย่างเช่น "ส่งคืนองค์ประกอบ ... จนกว่าเงื่อนไขจะประเมินว่าเป็นเท็จ"
ปีเตอร์

คำตอบ:


161

TakeWhileหยุดเมื่อเงื่อนไขเป็นเท็จWhereดำเนินการต่อและค้นหาองค์ประกอบทั้งหมดที่ตรงกับเงื่อนไข

var intList = new int[] { 1, 2, 3, 4, 5, -1, -2 };
Console.WriteLine("Where");
foreach (var i in intList.Where(x => x <= 3))
    Console.WriteLine(i);
Console.WriteLine("TakeWhile");
foreach (var i in intList.TakeWhile(x => x <= 3))
    Console.WriteLine(i);

ให้

Where
1
2
3
-1
-2
TakeWhile
1
2
3

31

Where สามารถตรวจสอบลำดับทั้งหมดเพื่อค้นหารายการที่ตรงกัน

Enumerable.Range(1, 10).Where(x => x % 2 == 1)
// 1, 3, 5, 7, 9

TakeWhile หยุดมองเมื่อพบสิ่งที่ไม่ใช่คู่แรก

Enumerable.Range(1, 10).TakeWhile(x => x % 2 == 1)
// 1

คำตอบที่สั้นและไพเราะสมบูรณ์แบบ
Neuron

10

MSDN กล่าว

Enumerable.TakeWhile Method

ส่งคืนองค์ประกอบจากลำดับตราบเท่าที่เงื่อนไขที่ระบุเป็นจริงจากนั้นข้ามองค์ประกอบที่เหลือ

Enumerable.Where

กรองลำดับของค่าตามเพรดิเคต

ความแตกต่างคือการEnumerable.TakeWhile ข้ามองค์ประกอบที่เหลือจากองค์ประกอบแรกที่ไม่ตรงกันว่าตรงกับเงื่อนไขหรือไม่


9

[1, 3, 5, 7, 9, 0, 2, 4, 6, 8]สมมติว่าคุณมีอาร์เรย์ที่ประกอบด้วย ตอนนี้:

var whereTest = array.Where(i => i <= 5);[1, 3, 5, 0, 2, 4]จะกลับมา

var whileTest = array.TakeWhile(i => i <= 5);[1, 3, 5]จะกลับมา


ฉันคิดว่า whileTest จะส่งคืนเพียง 1 เท่านั้นขึ้นอยู่กับคำตอบของ @David B และ @Albin Sunnanbo
Mohammed Thabet

ไม่จะส่งคืนสินค้าจนกว่าจะไม่ตรงตามเงื่อนไข ในกรณีนี้ 1, 3 และ 5 ตรงตามเงื่อนไข (คือ <= 5)
Jim Mischel

7

ลำดับของลำดับที่ส่งผ่านนั้นมีความสำคัญอย่างยิ่งTakeWhileซึ่งจะยุติทันทีที่เพรดิเคตส่งกลับfalseในขณะที่Whereจะประเมินลำดับต่อไปนอกเหนือจากfalseค่าแรก

การใช้งานทั่วไปสำหรับTakeWhileคือในระหว่างการประเมินค่าขนาดใหญ่ราคาแพงหรือแม้กระทั่งจำนวนนับไม่ถ้วนซึ่งคุณอาจมีความรู้เพิ่มเติมเกี่ยวกับลำดับของลำดับ

เช่นระบุลำดับ:

IEnumerable<BigInteger> InfiniteSequence()
{
    BigInteger sequence = 0;
    while (true)
    {
        yield return sequence++;
    }
}

A .Whereจะส่งผลให้เกิดการวนซ้ำที่ไม่มีที่สิ้นสุดซึ่งพยายามประเมินส่วนหนึ่งของการนับ:

var result = InfiniteSequence()
    .Where(n => n < 100)
    .Count();

ในขณะที่ a .TakeWhileและติดอาวุธด้วยความรู้ที่แจงนับจากน้อยไปหามากจะช่วยให้สามารถประเมินลำดับบางส่วนได้:

var result = InfiniteSequence()
    .TakeWhile(n => n < 100)
    .Count();

1
แน่นอน. นอกจากนี้ยังมีประโยชน์มากสำหรับการแยกวิเคราะห์ลำดับของโทเค็น
Aluan Haddad

7

แม้ว่าคำตอบที่มีอยู่จะถูกต้อง แต่ก็ไม่มีคำตอบใดที่ชี้ให้เห็นว่าเหตุใดคุณจึงต้องการใช้ TakeWhile หากผลลัพธ์จะเหมือนกัน: ประสิทธิภาพ สมมติว่าคุณมีรายการสั่งซื้อที่มีสินค้า 2 พันล้านรายการอยู่ในนั้นและคุณต้องการรายการที่ (อาจ 10 หรือ 15 รายการ) น้อยกว่าค่าที่กำหนด ประโยค Where จะตรวจสอบรายการทั้งหมด 2 พันล้านรายการในขณะที่ TakeWhile จะหยุดทันทีที่พบว่าค่าเท่ากับหรือมากกว่ามูลค่าที่คุณให้มา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.