我习惯这样做(来自其他语言):
 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).我熟悉创建列表和访问它们的元素.)
Jon*_*nna 77
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,但这不是唯一可能的灵感来源)
Eri*_*ips 23
假设.Net 3.5具有相等长度的列表:
var a = new List<int>() { 1, 2, 3 };
var b = new List<int>() { 5, 1, 2 }; 
var c = a.Select((x, i) => b[i] * x);
结果:
五
2
6
Sco*_*ain 19
如果您不使用.NET 4.0,那么如何编写自己的扩展方法来执行Zip.
static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector) 
{
    using (IEnumerator<TFirst> e1 = first.GetEnumerator())
    using (IEnumerator<TSecond> e2 = second.GetEnumerator())
    {
        while (e1.MoveNext() && e2.MoveNext())
        {
            yield return resultSelector(e1.Current, e2.Current);
        }
    }
}
GEE*_*EEF 12
对于没有LINQ的.NET版本,我建议使用for循环来完成此任务:
List<int> list1 = new List<int>(){4,7,9};
List<int> list2 = new List<int>(){11,2,3};
List<int> newList = new List<int>();
for (int i = 0; i < list1.Count; ++i)
{
    newList.Add(Math.Max(list1[i], list2[i]));
}
当然,这假设列表大小相同而不会改变.如果您提前知道列表大小,也可以将其实例化为正确的大小,那么只需在循环期间设置元素即可.
| 归档时间: | 
 | 
| 查看次数: | 2677 次 | 
| 最近记录: |