有没有办法在没有枚举fooCollection
两次的情况下使用linq执行此操作?
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;
答案 0 :(得分:13)
是的,您可以使用Enumerable.Aggregate方法:
var result = fooCollection.Aggregate(new FooResult(),
(r,f) =>
{
r.SelectedIds.Add(f.Id);
r.Content += f.Content;
return r;
});
这样可以避免副作用。我不喜欢LINQ中的副作用。 =)
答案 1 :(得分:2)
有一种可能性,但我认为这是一种黑客行为:
var aggregateContent = String.Empty;
var selectedIds = foo.Select(x => { aggregateContent += x.Content;
return x.Id; })
.ToList();
我会选择你已经拥有的循环。它可以提供更清晰的任何LINQ解决方案。
答案 2 :(得分:1)
你可以这样做:
foo.ForEach(x => { selectedIds.Add(x.Id); aggregateContent += x.Content; });
我建议不要将内容连接成字符串,而是使用StringBuilder
代替。
修改强>
如果您没有为ForEach
实现IEnumerable
的LINQ扩展库,可以使用以下方法:
public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach(T item in enumeration)
{
action(item);
}
}
答案 3 :(得分:0)
您要求的是让Linq语句产生两个结果。 linq的整个想法是允许简洁的函数编程风格,没有副作用。
如果您想要多个结果和良好的性能,则不应使用Linq,并使用常规foreach。
答案 4 :(得分: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 }