类似于集合的查询范围等产品

时间:2012-07-27 08:33:33

标签: c# linq

有没有一种很好的方式来写这样的东西:

foreach ((i,j) in PRODUCTOF(Range1, Range2))

PRODUCTOF(Range1, Range2).Sum((i,j) => i+17*j)

凡PRODUCTOF对我来说不为人知。

当然,您可以绕过这个或为此编写函数,但也许有一个应该更喜欢的内置语法。

2 个答案:

答案 0 :(得分:4)

你的意思是:

foreach (var pair in Range1.SelectMany(x => Range2, (x, y) => new { x, y }))
{
    // Use pair.x and pair.y
}

或者您的Sum示例:

var sum = Range1.SelectMany(x => Range2, (x, y) => new { x, y })
                .Sum(pair => pair.x + pair.y * 17);

作为查询表达式:

var query = from x in Range1
            from y in Range2
            select new { x, y };
var sum = query.Sum(pair => pair.x + pair.y * 17);

这假设您需要跨产品 - 每个可能的对。如果您只想尝试成对{ Range1(0), Range2(0) }, { Range1(1), Range2(1) }等,那么您应该使用Zip代替。

答案 1 :(得分:1)

如果SelectMany过于冗长,我总是可以写一个扩展程序,我想是这样的,

public static class Extensions
{
    public static IEnumerable<Tuple<T,T>> CartesianProduct<T>(
            this IEnumerable<T> source,
            IEnumerable<T> multiplier)
    {
        return source.SelectMany(s => multiplier, (s, m) => Tuple.Create(s, m));   
    }
}

你可以使用

Range1.CartesianProduct(Range2).Sum(p => p.item1+17*p.item2);

但是,我不确定你会获得那么多。如你所知,你可以更进一步,

public static class Extensions
{
    public static IEnumerable<TResult> CartesianProduct<T, TResult>(
            this IEnumerable<T> source,
            IEnumerable<T> multiplier,
            Func<T, T, TResult> combiner)
    {
        return source.SelectMany(s => multiplier, (s, m) => combiner(s, m));   
    }
}

并像这样使用,

Range1.CartesianProduct(Range2, (x, y) => x+17*y).Sum();

看起来有点整洁。


无论哪种方式,信用都会转到Jon Skeet以提供我穿着的窗口。