有没有一种很好的方法来写这样的东西:
foreach ((i,j) in PRODUCTOF(Range1, Range2))
或者
PRODUCTOF(Range1, Range2).Sum((i,j) => i+17*j)
其中 PRODUCTOF 对我来说是未知的。
当然,您可以绕过它或为此编写一个函数,但也许有一种人们应该喜欢的内置语法。
你的意思是这样的:
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
。
如果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提供了我已经穿好的窗户。