关于LINQ:Select 和select many的差异

Select and select many difference

我已经阅读了许多关于选择和选择LINQ中的许多站点/线程,但仍然不太理解。

select是否返回集合中的一个元素并选择many flatten a collection(例如list>())?

谢谢


这是一个样品。希望它能澄清一切:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
}

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


selectmany为传递到表达式中的每个对象返回多个对象。SELECT ISTEAD为传递到表达式中的每个对象返回单个对象。

引用文档:

选择许多

Projects each element of a sequence to an IEnumerable<(Of <(T>)>) and flattens the resulting sequences into one sequence.

选择

Projects each element of a sequence into a new form.

如果您想平展层次结构,可以使用SelectMany。例如,如果您有OrdersOrderDetails。如果您希望根据订单进行选择,但您希望返回OrderDetails,请使用SelectMany

1
2
3
4
5
6
7
8
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);


让我们依次讨论您的问题:

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

但是,是的,它返回一个序列(/collection),其中包含所有这些元素(例如下面的示例中的偶数sqare)。

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

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

2。&;是否选择多个展平集合(例如,列表>())?

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 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采用两个集合,而不是一个集合。
  • "even"是第一个集合,odd是第二个集合,我们使用lambda传递它,如"n=>odd"。(这是人们说它变平的地方)
  • 第三个参数(在上面的语句中,第二个参数)是treult,它给了我们交叉连接的输出,如果我们理解它,这就是selectmany的优点。
  • 享受学习。