LINQ ở đâu so với mất thời gian


99

Tôi muốn có sự khác biệt giữa các phương thức LINQ mang theo và ở đâu. Tôi lấy dữ liệu sau từ MSDN. Nhưng nó không có ý nghĩa với tôi

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

Lọc một chuỗi các giá trị dựa trên một vị từ.

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

Trả về các phần tử từ một chuỗi miễn là điều kiện được chỉ định là đúng.

Tất cả các ý kiến ​​đều được hoan nghênh.


1
Câu hỏi hay - Intellisense trên TakeWhile vẫn nói "Trả về các phần tử ... miễn là một điều kiện được chỉ định là đúng". Điều này rất có thể được hiểu giống như Where. Thay vào đó, từ ngữ phải là một cái gì đó như "Trả về các phần tử ... cho đến khi điều kiện được đánh giá là sai".
Peter

Câu trả lời:


159

TakeWhile dừng khi điều kiện sai, Tiếp tục ở đâu và tìm tất cả các phần tử phù hợp với điều kiện

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

Cho

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

30

Where có thể kiểm tra toàn bộ chuỗi để tìm kiếm các kết quả phù hợp.

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

TakeWhile ngừng tìm kiếm khi nó gặp phải sự không trùng khớp đầu tiên.

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

9

Giả sử bạn có một mảng có chứa [1, 3, 5, 7, 9, 0, 2, 4, 6, 8]. Hiện nay:

var whereTest = array.Where(i => i <= 5);sẽ trở lại [1, 3, 5, 0, 2, 4].

var whileTest = array.TakeWhile(i => i <= 5);sẽ trở lại [1, 3, 5].


Tôi nghĩ whileTest sẽ trở lại chỉ có 1 phụ thuộc vào @ David B và @Albin Sunnanbo câu trả lời
Mohammed Thabet

Không, nó sẽ trả lại các mặt hàng cho đến khi điều kiện không được đáp ứng. Trong trường hợp này, 1, 3 và 5 thỏa mãn điều kiện (chúng <= 5).
Jim Mischel

8

MSDN nói

Enumerable.TakeWhile Method

Trả về các phần tử từ một chuỗi miễn là điều kiện đã chỉ định là đúng, sau đó bỏ qua các phần tử còn lại.

Enumerable.Where

Lọc một chuỗi các giá trị dựa trên một vị từ.

Sự khác biệt là Enumerable.TakeWhile bỏ qua các phần tử còn lại từ phần không khớp đầu tiên cho dù chúng có khớp với điều kiện hay không


6

Mặc dù các câu trả lời hiện tại đều đúng, nhưng không ai trong số chúng chỉ ra lý do tại sao bạn muốn sử dụng TakeWhile nếu kết quả giống nhau: Hiệu suất. Giả sử bạn có một danh sách có thứ tự với 2 tỷ mặt hàng trong đó và bạn muốn những cái (có thể là 10 hoặc 15 mặt hàng) ít hơn một vallue nhất định. Mệnh đề Where sẽ kiểm tra tất cả 2 tỷ mục, trong khi TakeWhile sẽ dừng ngay khi tìm thấy giá trị bằng hoặc lớn hơn giá trị bạn cung cấp


5

Thứ tự của chuỗi được truyền là hoàn toàn quan trọng TakeWhile, sẽ kết thúc ngay sau khi một vị từ trả về false, trong khi Wheresẽ tiếp tục đánh giá chuỗi vượt quá falsegiá trị đầu tiên .

Một cách sử dụng phổ biến TakeWhilelà trong quá trình đánh giá lười biếng các bảng liệt kê lớn, đắt tiền hoặc thậm chí vô hạn, nơi bạn có thể có thêm kiến ​​thức về thứ tự của dãy.

Ví dụ: Cho chuỗi:

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

Một .Wheresẽ dẫn đến một vòng lặp vô hạn cố gắng đánh giá một phần của liệt kê:

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

Trong khi đó a .TakeWhilevà được trang bị kiến ​​thức mà các liệt kê tăng dần sẽ cho phép đánh giá trình tự từng phần:

var result = InfiniteSequence()
    .TakeWhile(n => n < 100)
    .Count();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.