开发者

How can I reduce a list by or-ing all its elements together?

If I'm not mistaken, Linq's .Aggregate works like reduce() in other languages, doesn't it?

Anyway, I'm trying this:

var tags = new[] { "a", "b", "c", ... };
tag.Rule = tags.Aggregate((x, y) => T开发者_运维百科oTerm(x) | y);

But it won't compile because the return type of my lambda has to be a string. So how can I get this to work?

I know it looks funny, because of the types (this is going into an Irony grammar), but all you really need to know that ToTerm() returns a KeyTerm, and KeyTerms can be or'd together to make a BnfExpression, which is what tag.Rule is expecting.


You're calling the Aggregate<TSource>(IEnumerable<TSource>, Func<TSource, TSource, TSource>) overload, which uses the first value in the sequence as the initial accumulator value.

If you want the accumulator to have a different type from the elements in the sequence, you'll need to specify the initial accumulator value yourself:

tag.Rule = tags.Aggregate(BnfExpression.Empty, (x, y) => ToTerm(x) | y);


Anon's solution won't work if there's no concept of an empty/identity value.

In my case, there isn't. At least not that I've found.

Thus, I've written this extra overload:

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

Which allows you to process the first element separately. You can call it like this:

tagName.Rule = tags.Aggregate(first => (BnfExpression)ToTerm(first), (seed, item) => seed | item);


If it makes more sense visually, you can also pre-convert with .Select:

tag.Rule = tags
    // turn the list into our expected result type
    .Select(item => ToTerm(item))
    // now reduce
    .Aggregate( (seed,item) => seed | item );

Which is pretty much the same thing as @Anon's answer using an explicit seed value:

var initialSeed = default(TagRule); // or whatever it should be so logic works
tag.Rule = tags.Aggregate( initialSeed, (seed, item) => seed | ToTerm(item) );
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜