如果我没弄错的话,Linq的.Aggregate
就像其他语言的reduce()
一样,不是吗?
无论如何,我正在尝试这个:
var tags = new[] { "a", "b", "c", ... };
tag.Rule = tags.Aggregate((x, y) => ToTerm(x) | y);
但它不会编译,因为我的lambda的返回类型必须是一个字符串。那我怎么能让它发挥作用呢?
我知道它看起来很有趣,因为类型(这是一个反复的语法),但你真的需要知道ToTerm()
会返回KeyTerm
和KeyTerms
可以或者一起制作BnfExpression
,这就是tag.Rule所期待的。
答案 0 :(得分:6)
您正在调用Aggregate<TSource>(IEnumerable<TSource>, Func<TSource, TSource, TSource>)
重载,它使用序列中的第一个值作为初始累加器值。
如果希望累加器与序列中的元素具有不同的类型,则需要自己指定初始累加器值:
tag.Rule = tags.Aggregate(BnfExpression.Empty, (x, y) => ToTerm(x) | y);
答案 1 :(得分:2)
如果没有空/身份值的概念,Anon的解决方案将无效。
就我而言,没有。至少不是我找到的。
因此,我写了这个额外的重载:
public static TRet Aggregate<TRet, TVal>(this IEnumerable<TVal> e, Func<TVal, TRet> seed, Func<TRet, TVal, TRet> func)
{
return e.Skip(1).Aggregate(seed(e.First()), func);
}
允许您分别处理第一个元素。你可以这样称呼它:
tagName.Rule = tags.Aggregate(first => (BnfExpression)ToTerm(first), (seed, item) => seed | item);
答案 2 :(得分:1)
如果它在视觉上更有意义,您还可以使用.Select
预转换:
tag.Rule = tags
// turn the list into our expected result type
.Select(item => ToTerm(item))
// now reduce
.Aggregate( (seed,item) => seed | item );
与@ Anon使用显式种子值的答案几乎相同:
var initialSeed = default(TagRule); // or whatever it should be so logic works
tag.Rule = tags.Aggregate( initialSeed, (seed, item) => seed | ToTerm(item) );