9

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

问题是所有聚合示例都使用支持“+”运算符的类型 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<>.Add 返回 void。Aggregate 的第二个参数的返回类型需要是 List。

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

list + item

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

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

4

5 回答 5

29

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

var newSet = set.Aggregate(new List<DestinationType>(),
                                    (list, item) =>
                                    {
                                        list.Add(new DestinationType(item.A, item.B, item.C));
                                        return list;
                                    });
于 2009-06-13T17:02:49.613 回答
10

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

context.Items
  .Select(item => new DestinationType(item.A, item.B, item.C))
  .ToList();
于 2009-06-13T16:56:31.657 回答
4

你可以在select这里申请。

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

Aggregate(通常称为foldor reduce)用于元素组合在一起,其中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,使用达斯汀的解决方案或者更好地为不可变集合实现一个基于链表的类型(你甚至可以给这个类型一个operator +)。

于 2009-06-13T17:07:14.703 回答
3
list.AddRange(context.Items.Select(item => 
  new DestinationType(item.A, item.B, item.C));

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

于 2009-06-13T17:29:22.403 回答
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);
于 2011-02-21T11:40:57.560 回答