【问题标题】:How to add to a list using Linq's aggregate function C#如何使用 Linq 的聚合函数 C# 添加到列表
【发布时间】:2011-02-21 19:40:57
【问题描述】:

我有一个类型的对象集合,我想将它们转换为不同的类型。这可以通过 foreach 轻松完成,但我想弄清楚如何使用 Linq 的聚合函数来做到这一点。

问题是所有聚合示例都使用行字符串或整数类型,它们支持“+”运算符。我想让累加器类型是一个列表,它不支持“+”语义。

这是一个简单的例子:

public class DestinationType
{
    public DestinationType(int A, int B, int C) { ... }
}

var set = from item in context.Items
          select new { item.A, item.B, item.C };

var newSet = set.Aggregate( new List<DestinationType>(),
                            (list, item) => list.Add(new DestinationType(item.A, item.B, item.C)) );

问题在于 List.Add 返回 void。 Aggregate 的第二个参数的返回类型需要是 List。

如果我有一个支持“+”类型语义的列表类型,我可以只做第二个参数

list + item

但是我找不到任何支持这种东西的集合类型。

似乎这在 Linq 中应该很容易实现。有办法吗?另外,如果我错过了一个更简单的方法,我也很想了解这一点。谢谢!

【问题讨论】:

  • 感谢您的所有精彩回答! Sam & Talljoe 的回答最简单地使用 Linq 完成了这一点。再次感谢!

标签: c# linq aggregate


【解决方案1】:

假设这是 LINQ to Objects,请尝试...

var newSet = set.Aggregate(new List<DestinationType>(),
                                    (list, item) =>
                                    {
                                        list.Add(new DestinationType(item.A, item.B, item.C));
                                        return list;
                                    });

【讨论】:

    【解决方案2】:

    我认为调用SelectToList() 可能是您需要的。例如:

    context.Items
      .Select(item => new DestinationType(item.A, item.B, item.C))
      .ToList();
    

    【讨论】:

      【解决方案3】:

      你可以在这里申请select

      var newSet = set.Select(item => new DestinationType(...)).ToList();
      

      Aggregate(通常称为foldreduce)用于将元素组合在一起,其中select 将函数应用于每个元素。

      例如:

      f 是一元函数,那么 [a, b, c].select(f) 等于 [f(a), f(b), f(c)]

      f为二元函数,则[a, b, c].aggregate(f, init)等于f(a, f(b, f(c, init)))

      您在示例中选择的方式在 C# 中并不常见,但经常用于函数式编程中,其中(链接)列表被转换为新列表,而不是更改现有集合:

      reversed = fold (\list element -> element:list) [] [1..10]
      

      如果您真的想使用 aggregate 进行此计算,请使用 Dustin 的解决方案或更好地为不可变集合实现基于链表的类型(您甚至可以为这种类型指定 operator +)。

      【讨论】:

        【解决方案4】:
        list.AddRange(context.Items.Select(item => 
          new DestinationType(item.A, item.B, item.C));
        

        我知道它不使用 Aggregate 函数,但您可能应该找到一个更好的示例来学习聚合。

        【讨论】:

          【解决方案5】:

          除非我遗漏了一些明显的东西,否则为什么不这样做:

          public class DestinationType
          {
              public DestinationType(int A, int B, int C) { ... }
          }
          
          var newSet = from item in context.Items
              select new DestinationType(item.A, item.B, item.C);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-03-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-22
            • 1970-01-01
            • 2011-04-08
            相关资源
            最近更新 更多