Linq: Sự khác biệt giữa Chọn và Ở đâu


122

Các SelectWherephương pháp có sẵn trong Linq. Mọi nhà phát triển nên biết gì về hai phương pháp này? Ví dụ: khi nào sử dụng cái này hơn cái kia, bất kỳ lợi thế nào của việc sử dụng cái này hơn cái kia, v.v.


7
Tôi không nghĩ câu hỏi này nên được đánh dấu là CW, nó có thể có câu trả lời chắc chắn.
Brandon

1
@Brandon không có gì sai khi đánh dấu một cái gì đó CW nếu nó là khách quan.
Rex M

@Rex, tôi đồng ý. Chỉ nói rằng sự khác biệt giữa Chọn và Nơi có câu trả lời chắc chắn và phần thứ hai của câu hỏi có thể dựa trên các phương pháp thường được chấp nhận. Tôi chỉ chỉ ra nó trong trường hợp OP không chắc chắn về việc đánh dấu mọi thứ là CW. Nếu anh ta có ý định cho nó là CW, thì tôi sẽ ổn.
Brandon

6
Có rất nhiều điều sai trái với nó. CW là vô ích, và nhận được nhiều hơn như vậy khi người ta đánh dấu câu hỏi hoàn toàn ngẫu nhiên như CW
jalf

Câu trả lời:


126

Ở đâu

tìm các mục phù hợp và chỉ trả về những mục phù hợp ( lọc ).

-> IEnumerable<A>vào, IEnumerable<A>ra

Lựa chọn

trả về một cái gì đó cho tất cả các mục trong nguồn ( phép chiếu / chuyển đổi ). Cái gì đó có thể là chính các mục, nhưng thường là một phép chiếu của một số loại.

-> IEnumerable<A>vào, IEnumerable<B>ra


15
Selectsẽ luôn trả về cùng một số phần tử trong danh sách (bất kể bạn có thể có điều kiện lọc nào). Wherecó thể trả về ít phần tử hơn tùy thuộc vào điều kiện bộ lọc của bạn.
goku_da_master

đây là một ví dụ MSDN của selectđây là một trong chowhere
yazanpro

Ít nhất đối với tôi, có một số nền tảng với các ngôn ngữ khác, nó giúp chúng ta nghĩ rằng Where == filterSelect == map
bgusach

52

SelectWhere là hai toán tử hoàn toàn khác nhau hoạt động trên IEnumerable s.

Cái đầu tiên chúng ta gọi là Toán tử chiếu , còn cái cuối cùng là Toán tử hạn chế .

Một cách thú vị để có cái nhìn sâu sắc về hành vi của các toán tử như vậy là xem xét "loại chức năng" của họ.

  • Chọn: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; nó nhận cả đầu vào là IEnumerable chứa các phần tử kiểu T1 và một hàm biến đổi các phần tử kiểu T1 thành các phần tử kiểu T2. Đầu ra là IEnumerable chứa các phần tử kiểu T2.

    Từ đó, người ta có thể dễ dàng đoán rằng toán tử này sẽ tạo ra đầu ra của nó bằng cách áp dụng hàm đầu vào trên từng phần tử của IEnumerable đầu vào, và gói kết quả bên trong IEnumerable mới.

    Sử dụng một số ký hiệu giống như toán học, nó nhận làm đầu vào (a, b, c, ...): IEnumerable <T1>f: T1 → T2 và tạo ra (f (a), f (b), f (c) , ...): IEnumerable <T2>

  • Trong đó: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; cái này lấy IEnumerable chứa các phần tử của kiểu T1 và một vị từ trên T1 (nghĩa là một hàm tạo ra kết quả boolean cho đầu vào kiểu T1). Bạn thấy rằng đầu ra cũng là một IEnumerable chứa các phần tử của kiểu T1.

    Lần này, người ta sẽ đoán rằng một phần tử của IEnumerable đầu vào sẽ có mặt trên IEnumerable đầu ra tùy thuộc vào kết quả của việc áp dụng vị từ cho phần tử. Thêm vào đó ngữ nghĩa của tên toán tử, bạn có thể chắc chắn rằng nó sẽ tạo ra đầu ra IEnumerable bằng cách lấy từ đầu vào một chỉ những phần tử đánh giá là true trên ứng dụng của vị từ.

Những người có nền tảng lập trình chức năng thường nghĩ như thế này. Nó cho phép bạn suy luận (hoặc ít nhất là đoán ...) những gì một toán tử làm chỉ bằng cách nhìn vào kiểu của nó!

Như một bài tập, hãy thử xem các toán tử khác được LINQ giới thiệu trên IEnumerables và suy ra hành vi của chúng, trước khi xem tài liệu!


47

Chúng khác nhau:

Selectlà tất cả về sự biến đổi .

Wherelà tất cả về lọc .


18

Chọn ánh xạ một cấu trúc có thể liệt kê. Nếu bạn thực hiện một lựa chọn trên IEnumerable, bạn sẽ nhận được một mảng có cùng số phần tử, nhưng kiểu khác tùy thuộc vào ánh xạ bạn đã chỉ định. Nơi lọc IEnumerable để nó cung cấp cho bạn một tập hợp con của IEnumerable gốc.



7

Nếu bạn biết họ đã triển khai các phương pháp mở rộng ở đâu và chọn lọc như thế nào, bạn có thể dự đoán nó đang làm gì ... Tôi đã cố gắng triển khai ở đâu và chọn các phương pháp mở rộng ... Bạn có thể xem qua ...

Nơi thực hiện ::

public static IEnumerable<Tsource> Where<Tsource> ( this IEnumerable<Tsource> a , Func<Tsource , bool> Method )
{

    foreach ( var data in a )
    {
        //If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return)
        if ( Method.Invoke ( data ) )
        {
            yield return data;
        }
    }
}

Chọn triển khai ::

public static IEnumerable<TResult> Select<TSource , TResult> ( this IEnumerable<TSource> a , Func<TSource , TResult> Method )
{
    foreach ( var item in a )
    {
        //Each iteration call the delegate and return the Data back.(use 'yield' for deferred return)
        yield return Method.Invoke ( item );
    }
}

Việc triển khai của tôi hoạt động tốt cho bất kỳ bộ sưu tập nào ... Nhưng nó khác với các phương pháp Mở rộng đã triển khai của Microsoft, Bởi vì chúng sử dụng cây biểu thức để triển khai giống nhau.


1

Trong trường hợp Chọn nó, bạn có thể ánh xạ tới IEnumerable của một cấu trúc mới.

  A.Select(x=>new X{UID=x.uid, UNAME=x.uname}) 
  //input as [IEnumerable<A>] -------->  return output as [IEnumerable<X> ]

Where () hoạt động như một bộ lọc đối với IEnumerable, nó sẽ trả về kết quả dựa trên mệnh đề where.

A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] -------->  return output as [IEnumerable<A> ]
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.