我习惯于这样做(从其他语言):
a = 1, 2, 3;
b = 5, 1, 2;
c = a * b; // c = 5, 2, 6
这需要两个大小相等的列表,并将一个函数应用于它们的成员,一次一个,以获取结果列表。它可能是一个简单的函数(如上面的乘法),或者更复杂的函数:
c = b>a ? b-a : 0; // c = 4, 0, 0
我可以想到在C#中执行此操作的几种不同方法,但是我不确定受过C#培训的程序员如何做到这一点。在C#世界中解决此问题的正确方法是什么?
(我要问的唯一部分是在哪里 c = f(a,b)
。我熟悉创建列表并访问其元素。)
var c = a.Zip(b, (x, y) => x * y);
对于修改后的更复杂的代码:
var c = a.Zip(b, (x, y) => x > y ? x - y : 0);
请注意,Zip
既扩展方法从Enumerable
作用上IEnumerable<T>
和Queryable
作用在IQueryable<T>
,所以它是可能的,如果拉姆达是一个给定的查询提供可以处理,它可以作为一个数据库的SQL查询来处理,或者.NET中的内存以外的其他方式。
有人在评论中提到这是4.0的新功能。自己为3.5实现并不难:
public class MyExtraLinqyStuff
{
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
{
//Do null checks immediately;
if(first == null)
throw new ArgumentNullException("first");
if(second == null)
throw new ArgumentNullException("second");
if(resultSelector == null)
throw new ArgumentNullException("resultSelector");
return DoZip(first, second, resultSelector);
}
private static IEnumerable<TResult> DoZip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
{
using(var enF = first.GetEnumerator())
using(var enS = second.GetEnumerator())
while(enF.MoveNext() && enS.MoveNext())
yield return resultSelector(enF.Current, enS.Current);
}
}
对于.NET2.0或.NET3.0,您可以使用相同的方法,但不能将其作为扩展方法,它可以从注释中回答另一个问题。当时在.NET中确实没有一种惯用的方式来做这些事情,或者至少在当时我们用.NET进行编码的人们之间没有达成共识。我们中的一些人在我们的工具包中有类似上面的方法(虽然显然不是扩展方法),但是更多的是,我们受其他语言和库的影响比其他任何事情(例如,由于我从中学到的东西,我正在做类似上面的事情C ++的STL,但这几乎不是唯一的灵感来源)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句