2010-03-11 39 views
6

Tôi đã đọc nhiều trang/chủ đề về lựa chọn và chọn nhiều trong LINQ nhưng vẫn không hoàn toàn hiểu.Chọn và chọn nhiều sự khác biệt

Có chọn trả về một phần tử trong bộ sưu tập và chọn nhiều bộ sưu tập phẳng (ví dụ: Danh sách>()) không?

Cảm ơn

+2

câu hỏi song song - xem http://stackoverflow.com/questions/958949/difference-between-select-and-selectmany để có câu trả lời tuyệt vời. –

Trả lời

5

Đây là mẫu. Hy vọng nó làm rõ mọi thứ:

static void MethodRun() 
{ 
    List<Topping> testToppings = new List<Topping> { Topping.Cheese, Topping.Pepperoni, Topping.Sausage }; 

    var firstLetterofToppings = testToppings.Select(top => top.ToString().First()); 

    // returns "C, P, S" 

    var singleToppingPizzas = testToppings.Select(top => new Pizza(top)).ToArray(); 

    // returns "Pizza(Cheese), Pizza(Pepperoni), Pizza(Sausage)" 

    List<Topping> firstPizza = new List<Topping> { Topping.Cheese, Topping.Anchovies }; 
    List<Topping> secondPizza = new List<Topping> { Topping.Sausage, Topping.CanadianBacon, Topping.Pepperoni }; 
    List<Topping> thirdPizza = new List<Topping> { Topping.Ham, Topping.Pepperoni }; 

    List<IEnumerable<Topping>> toppingsPurchaseOrder = new List<IEnumerable<Topping>> { firstPizza, secondPizza, thirdPizza }; 

    var toppingsToOrder = toppingsPurchaseOrder.SelectMany(order => order); 

    //returns "Cheese, Anchovies, Sausage, CanadianBacon, Pepperoni, Ham, Pepperoni" 

} 

class Pizza 
{ 
    public List<Topping> Toppings { get; private set; } 
    public Pizza(Topping topping) : this(new List<Topping> { topping }) { } 
    public Pizza(IEnumerable<Topping> toppings) 
    { 
     this.Toppings = new List<Topping>(); 
     this.Toppings.AddRange(toppings); 
    } 
} 

enum Topping 
{ 
    Cheese, 
    Pepperoni, 
    Anchovies, 
    Sausage, 
    Ham, 
    CanadianBacon 
} 

Điều quan trọng là Select() có thể chọn bất kỳ loại đối tượng nào. Đúng là bạn có thể chọn một thuộc tính của bất kỳ giá trị chung nào được gán cho bộ sưu tập của bạn, nhưng bạn cũng có thể chọn bất kỳ loại đối tượng nào khác. SelectMany() chỉ làm phẳng danh sách của bạn.

3

SelectMany trả lại số đối tượng cho mỗi đối tượng được chuyển vào biểu thức. Chọn istead trả về một đối tượng đơn cho mỗi đối tượng được chuyển vào biểu thức.

Để trích dẫn tài liệu:

Chọn Nhiều

dự án mỗi phần tử của một chuỗi vào một IEnumerable < (Tất < (T>)>) và flattens chuỗi kết quả thành một chuỗi .

Chọn

dự án mỗi phần tử của một chuỗi thành một hình thức mới.

Bạn có thể sử dụng SelectMany nếu bạn muốn làm phẳng phân cấp. Ví dụ. nếu bạn có OrdersOrderDetails. Nếu bạn muốn thực hiện lựa chọn dựa trên các đơn đặt hàng, nhưng bạn muốn trả lại số OrderDetails, hãy sử dụng SelectMany.

var result = db.Orders 
       .Where(x => x.CustomerId == 500) // input to next expression is IEnumerable<Order> 
       .SelectMany(x => x.OrderDetails) // input to next expression is IEnumerable<OrderDetails> 
       .Sum(x => x.PositionTotal); 

var result = db.Orders 
       .Where(x => x.CustomerId == 500) // input to next expression is IEnumerable<Order> 
       .Select(x => CustomerName); 
+0

OrderDetails phải là một trường kiểu OrderDetails trong đối tượng Orders, phải không? – dotnetdev

+0

Trong mẫu này ... có nó. :-) – AxelEckenberger

0

Hãy đi tuần tự qua câu hỏi của bạn:

1. Liệu chọn trở lại một phần tử trong một bộ sưu tập? -> Không, hoàn toàn không. 'chọn' trả về chính xác cùng một số phần tử trong bộ sưu tập, nhưng thành hình dạng khác nhau (nếu muốn).

Nhưng, vâng, nó trả về một chuỗi (/ bộ sưu tập) có tất cả các phần tử đó (ví dụ: even_sqare trong ví dụ bên dưới).

ví dụ
int[] even = {2,4}; int[] even_square = even.Select(n=> n*2).ToArray();

o/p
đầu ra even_square để {4,8} đó là chính xác như nhau trong đếm (2), nhưng dự báo khác nhau, chúng tôi đã hình vuông của mỗi bằng cách chọn chúng.

2. & chọn nhiều làm phẳng bộ sưu tập (ví dụ: Danh sách>())?

-> vâng, nhưng thực ra, nó giống như một sự kết hợp chéo với kiểm soát của chúng tôi.

int[] odd = { 1, 3 }; 
int[] even = { 2, 4 }; 

int[] crossjoin = 
     even.SelectMany(
       n => odd, //combining even with odd 
       (n,o)=>Convert.ToInt32(n.ToString()+o.ToString())//given many selects, decide our projection 
      ).ToArray(); 

foreach (var item in crossjoin) 
{ 
    Console.WriteLine(item); 
} 

Output: 21 
     23 
     41 
     43 

Bây giờ là một điều triệu đô la:

  • Không giống như hầu hết các nhà khai thác trong LINQ, SelectMany mất hai bộ sưu tập, thay vì một.
  • "thậm chí" là bộ sưu tập đầu tiên và kỳ quặc là bộ sưu tập thứ hai, mà chúng tôi đã chuyển bằng cách sử dụng lambda như thế này 'n => lẻ'. (đây là nơi mọi người nói nó làm phẳng)
  • thông số thứ ba (trong tuyên bố trên, tham số thứ hai) là TResult cho chúng ta đầu ra là tham gia chéo và đó là vẻ đẹp của SelectMany nếu chúng ta hiểu nó.
  • Thích học tập.
Các vấn đề liên quan