2010-03-11 81 views
6

我已经阅读了许多网站/选择线程并选择了许多LINQ,但仍然不太明白。选择并选择许多区别

是否select返回一个集合中的一个元素并选择多个flatten集合(例如List>())?

谢谢

+2

复制问题 - 请参阅http://stackoverflow.com/questions/958949/difference-between-select-and-selectmany以获得很好的答案。 – 2010-03-11 14:20:25

回答

5

下面是一个示例。希望它澄清一切:

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 
} 

关键是,选择()可以选择任何类型的对象。确实,您可以选择任何通用值分配给您的集合的属性,但您也可以选择任何其他类型的对象。 SelectMany()只是展平你的列表。

3

SelectMany返回一个对象数量为每个传递到表达式的对象。对于传递到表达式的每个对象,Select istead会返回一个单个对象

引述的文档:

选择许多

项目的序列中的每个元素到IEnumerable <(OF <(T>)>),将所得序列合并为一个序列。

选择

项目的序列中的每个元素到一个新的形式。

如果要平坦化层次结构,则可以使用SelectMany。例如。如果你有OrdersOrderDetails。如果您想根据订单进行选择,但您想要退货,请使用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必须是Orders对象中OrderDetails类型的字段,对吗? – dotnetdev 2010-03-11 14:57:22

+0

在这个例子中......是的。 :-) – AxelEckenberger 2010-03-11 14:59:23

0

让我们依次去了你的问题:在集合中

1.是否选择返回一个元素? - >不,绝对不是。 'select'返回的集合中元素的数量完全相同,但形状不同(如果需要)。

但是,是的,它返回一个包含所有元素的序列(/ collection)(例如,下面的例子中的even_sqare)。

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

O/P
even_square输出到{4,8}这是在计数完全相同(2),但不同的投影,我们给每个的平方通过选择它们。

2. &确实选择了许多扁平的集合(例如List>())?

- >是的,但实际上,它就像我们控制的交叉连接。

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 

现在一百万美元的事情:

  • 不像LINQ大多数运营商采用的SelectMany两个集合,而不是一个。
  • “偶数”是第一个集合,奇数是第二个集合,我们使用lambda传递的是'n => odd'。 (这是人们说它变平的地方)
  • 第三个参数(在上面的语句中,第二个参数)是TResult,它给出了交叉连接的输出,如果我们理解它的话,这就是SelectMany的美。
  • 享受学习。