【问题标题】:Select and select many difference选择和选择多的区别
【发布时间】:2011-01-26 09:40:20
【问题描述】:

我已经阅读了许多关于 select 的站点/线程,并在 LINQ 中选择了许多,但仍然不太明白。

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

谢谢

【问题讨论】:

标签: linq


【解决方案1】:

这是一个示例。希望它能澄清一切:

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() 只是将您的列表变平。

【讨论】:

    【解决方案2】:

    SelectMany 为传递到表达式中的每个对象返回一个对象数。 Select 会为传入表达式的每个对象返回一个单个对象

    引用文档:

    多选

    将序列的每个元素投影到 IEnumerable)>) 并将结果序列展平为一个序列。

    选择

    将序列的每个元素投影到一个新的形式中。

    如果您想扁平化层次结构,可以使用SelectMany。例如。如果你有OrdersOrderDetails。如果您想根据订单进行选择,但您想返回 OrderDetails,请使用 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);
    

    【讨论】:

    • OrderDetails 必须是 Orders 对象中 OrderDetails 类型的字段吧?
    • 在这个示例中......是的。 :-)
    【解决方案3】:

    让我们依次回答您的问题:

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

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

    例如
    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 采用两个集合,而不是一个。
    • "even" 是第一个集合,odd 是第二个集合,我们使用 lambda 传入,例如 'n = >odd'。 (这就是人们说它变平的地方)
    • 第三个参数(在上面的语句中,第二个参数)是 TResult,它为我们提供交叉连接的输出,如果我们理解它,这就是 SelectMany 的美妙之处。
    • 享受学习。

    【讨论】:

      猜你喜欢
      • 2012-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-04
      • 2012-06-07
      • 1970-01-01
      相关资源
      最近更新 更多