10

有没有办法用 linq 做到这一点而不枚举fooCollection两次?

var fooCollection = // get foo
var selectedIds = new List<int>();
var aggregateContent = String.Empty;

foreach (var f in foo)
{
    selectedIds.Add(foo.Id);
    aggregateContent += foo.Content
}

var results = new FooResults
{
    Content = aggregateContent,
    SelectedIds = selectedIds
};

return results;
4

5 回答 5

16

是的,您可以使用Enumerable.Aggregate方法:

var result = fooCollection.Aggregate(new FooResult(),
                                    (r,f) => 
                                    { 
                                        r.SelectedIds.Add(f.Id);
                                        r.Content += f.Content;
                                        return r;
                                    });

这具有无副作用的好处。我不喜欢 LINQ 中的副作用。=)

于 2012-10-17T14:38:18.390 回答
2

有一种可能性,但我认为这是一种黑客行为:

var aggregateContent = String.Empty;
var selectedIds = foo.Select(x => { aggregateContent += x.Content;
                                    return x.Id; })
                     .ToList();

我会选择你已经拥有的循环。它比您能想出的任何 LINQ 解决方案都干净得多。

于 2012-10-17T14:30:18.800 回答
1

你可以这样做:

foo.ForEach(x => { selectedIds.Add(x.Id); aggregateContent += x.Content; });

我建议不要将 Content 连接成一个字符串,而是使用 a StringBuilder

编辑

如果您没有实现ForEachfor的 LINQ 扩展库,IEnumerable可以使用以下方法:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action) 
{ 
    foreach(T item in enumeration) 
    { 
        action(item); 
    } 
} 
于 2012-10-17T14:28:33.460 回答
0

您要求的是让 Linq 语句产生两个结果。linq 的整个想法是允许简洁的函数式编程风格而没有副作用。

如果您想要多个结果和良好的性能,则不应使用 Linq,而应使用常规 foreach。

于 2012-10-17T14:39:56.633 回答
0

我也找不到所以我这样写

public static IEnumerable<V> SelectAggregate<T,V>(this IEnumerable<T> items,V seed,Func<V,T,V> func)
{
    foreach(var item in items)
    {
        seed    = func(seed,item);
        yield return seed;
    }
}


var array = new int[]{ 1,2,3 };
var sumArray = array.SelectAggregate(0,(seed,item) => seed + item).ToArray();
//// { 1,3,6 }
于 2018-07-25T03:15:58.917 回答