如何使用Linq的聚合函数C#添加到列表

时间:2009-06-13 16:53:29

标签: c# linq aggregate

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

问题是所有Aggregate示例都使用类型line string或int,它们支持'+'运算符。我希望累加器类型是一个列表,它不支持'+'语义。

这是一个简单的例子:

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&lt;&gt; .Add返回void。 Aggregate的第二个参数的返回类型需要是List。

如果我有一个支持'+'类型语义的列表类型,我可以创建第二个参数

list + item

但是我找不到任何支持此类事物的集合类型。

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

5 个答案:

答案 0 :(得分:25)

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

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

答案 1 :(得分:10)

我认为拨打SelectToList()的电话可能就是您需要的。例如:

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

答案 2 :(得分:4)

您可以在这里申请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 +)。 / p>

答案 3 :(得分:3)

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

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

答案 4 :(得分:1)

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

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);