2010-03-11 14 views
6

He leído muchos sitios/subprocesos en seleccionar y seleccionar muchos en LINQ pero todavía no entiendo del todo.Seleccionar y seleccionar muchas diferencias

¿Seleccionar devolver un elemento en una colección y seleccionar muchos aplanar una colección (por ejemplo, Lista>())?

Gracias

+2

pregunta dupe - vea http://stackoverflow.com/questions/958949/difference-between-select-and-selectmany para una excelente respuesta. –

Respuesta

5

Aquí hay un ejemplo. Espero que aclare todo:

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 
} 

La clave es que Select() puede seleccionar cualquier tipo de objeto. Es cierto que puede seleccionar una propiedad de cualquier valor genérico asignado a su colección, pero también puede seleccionar cualquier otro tipo de objeto. SelectMany() acaba de aplanar su lista.

3

SelectMany devuelve un número de objetos para cada uno de los objetos pasados ​​a la expresión. Select istead devuelve un solo objeto para cada objeto pasado a la expresión.

Para citar la documentación:

Seleccione Muchos

Proyecta cada elemento de una secuencia en una IEnumerable < (De < (T>)>) y reduce las secuencias resultantes en una secuencia .

Seleccione

Proyecta cada elemento de una secuencia en una nueva forma.

Puede usar SelectMany si desea aplanar una jerarquía. P.ej. si tiene Orders y OrderDetails. Si desea realizar una selección basada en los pedidos, pero desea que se devuelva el OrderDetails, use 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 debe ser un campo de tipo OrderDetails en el objeto Orders, ¿no? – dotnetdev

+0

En esta muestra ... sí lo hace. :-) – AxelEckenberger

0

Vamos secuencialmente sobre su pregunta:

1. ¿seleccione un elemento de retorno en una colección? -> No, absolutamente no. 'seleccionar' devuelve exactamente el mismo número de elementos que están en la colección, pero en forma diferente (si se desea).

Pero, sí, devuelve una secuencia (/ colección) que tiene todos esos elementos (por ejemplo, even_sqare en el ejemplo siguiente).

por ejemplo
int[] even = {2,4}; int[] even_square = even.Select(n=> n*2).ToArray();

o/p
salidas even_square a {4,8} que es exactamente el mismo en los recuentos (2), pero de proyección diferente, dimos cuadrados de cada seleccionándolas.

2. & selecciona muchos aplanar una colección (por ejemplo, Lista>())?

-> sí, pero en realidad, es como una combinación cruzada con nuestro control.

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 

Ahora una cosa del millón:

  • A diferencia de la mayoría de los operadores de LINQ, SelectMany toma dos colecciones, en lugar de uno.
  • "par" es la primera colección, e impar es la segunda colección, que pasamos usando lambda como este 'n => impar'. (Aquí es donde la gente dice que se aplana)
  • tercer parámetro (en la declaración anterior, segundo parámetro) es TResult que nos da salida que es de combinación cruzada y eso es belleza de SelectMany si lo entendimos.
  • Disfruta aprendiendo.