一次循环2个列表

我有两个长度相同的列表,是否可以一次循环这两个列表?

我正在寻找正确的语法来执行以下操作

foreach itemA, itemB in ListA, ListB { Console.WriteLine(itemA.ToString()+","+itemB.ToString()); } 

你认为这在C#中有可能吗? 如果是的话,lambda表达式与此相当的是什么?

[编辑]:澄清; 这在通用LINQ / IEnumerable上下文中非常有用,在这种上下文中你不能使用索引器,因为a:它不存在于可枚举中,而b:你不能保证你可以更多地读取数据不止一次。 由于OP提到了lambdas,所以LINQ可能不会太远(并且是的,我确实意识到LINQ和lambdas不是完全相同的事情)。

听起来你需要缺少Zip操作符; 你可以欺骗它:

 static void Main() { int[] left = { 1, 2, 3, 4, 5 }; string[] right = { "abc", "def", "ghi", "jkl", "mno" }; // using KeyValuePair<,> approach foreach (var item in left.Zip(right)) { Console.WriteLine("{0}/{1}", item.Key, item.Value); } // using projection approach foreach (string item in left.Zip(right, (x,y) => string.Format("{0}/{1}", x, y))) { Console.WriteLine(item); } } // library code; written once and stuffed away in a util assembly... // returns each pais as a KeyValuePair<,> static IEnumerable> Zip( this IEnumerable left, IEnumerable right) { return Zip(left, right, (x, y) => new KeyValuePair(x, y)); } // accepts a projection from the caller for each pair static IEnumerable Zip( this IEnumerable left, IEnumerable right, Func selector) { using(IEnumerator leftE = left.GetEnumerator()) using (IEnumerator rightE = right.GetEnumerator()) { while (leftE.MoveNext() && rightE.MoveNext()) { yield return selector(leftE.Current, rightE.Current); } } } 

相反,在一个普通的旧循环中做它会简单得多……

 for(int i=0; i 

你可以明确地做到这一点。

 IEnumerator ListAEnum = ListA.GetEnumerator(); IEnumerator ListBEnum = ListB.GetEnumerator(); ListBEnum.MoveNext(); while(ListAEnum.MoveNext()==true) { itemA=ListAEnum.getCurrent(); itemB=ListBEnum.getCurrent(); Console.WriteLine(itemA.ToString()+","+itemB.ToString()); } 

至少这个(或类似的东西)是编译器为foreach循环所做的。 我没有测试它,我猜想枚举器缺少一些模板参数。

只需从List和IEnumerator-Interface中查找GetEnumerator()。

我建议使用普通的旧for循环,但你应该考虑不同的数组长度。 所以

 for(int i=0; i 

可以变成

 for(int i = 0; i < Math.Min(ListA.Length, ListB.Lenght); i++) { Console.WriteLine(ListA[i].ToString() + ", " + ListB[i].ToString()); } 

甚至进入

  for(int i = 0; i < Math.Max(ListA.Length, ListB.Lenght); i++) { string valueA = i < ListA.Length ? listA[i].ToString() : ""; string valueB = i < ListB.Length ? listB[i].ToString() : ""; Console.WriteLine(valueA+ ", " + valueB); } 

我有同样的问题,但使用列表中包含列表的对象…为了它的价值,这可能会帮助有同样问题的人。

由于IndexOf是O(n),所以运行时间不是很好,但是当时我处理的内部 – foreach循环比这个例子要多得多,所以我不想处理迭代器变量。

在这种情况下,我非常想念PHPs foreach($ arrayList为$ key => $ value)表示法…也许我在C#中遗漏了一些东西,必须有一种方法可以在O(c)时间内获得索引! (遗憾的是这篇文章说不: 在’foreach’循环中获取数组键 )

 class Stock { string symbol; List hourlyPrice; // provides a list of 24 decimals } // get hourly prices from yesterday and today List stockMondays = Stocks.GetStock("GOOGL,IBM,AAPL", DateTime.Now.AddDay(-1)); List stockTuesdays = Stocks.GetStock("GOOGL,IBM,AAPL", DateTime.Now); try { foreach(Stock sMonday in stockMondays) { Stock sTuesday = stockTuesday[stockMondays.IndexOf(sMonday)]; foreach(decimal mondayPrice in sMonday.prices) { decimal tuesdayPrice = sTuesday.prices[sMonday.prices.IndexOf(mondayPrice)]; // do something now } } } catch (Exception ex) { // some reason why list counts aren't matching? } 

Senthil Kumar的科技博客 ,有一系列文章介绍了C#(Python)Itertools的实现 ,包括itertools.izip

从Itertools for C# – Cycle和Zip ,您可以获得任意数量的迭代 (不仅仅是List )的解决方案。 请注意, Zip在每次迭代时生成一个Array

 public static IEnumerable Zip(params IEnumerable[] iterables) { IEnumerator[] enumerators = Array.ConvertAll(iterables, (iterable) => iterable.GetEnumerator()); while (true) { int index = 0; T[] values = new T[enumerators.Length]; foreach (IEnumerator enumerator in enumerators) { if (!enumerator.MoveNext()) yield break; values[index++] = enumerator.Current; } yield return values; } 

}

代码获取所有迭代的枚举器,向前移动所有枚举器,将其当前值累积到数组中并生成数组。 它会在任何一个枚举器耗尽元素之前执行此操作。

我有这个小函数,它可以帮助我遍历这两个列表对象。 schema的类型为SqlData,它是一个包含三个属性的类。 数据是一个包含动态类型值的列表。 首先,我在遍历模式集合,而不是使用item的索引来遍历数据对象。

 public List SqlDataBinding(List schema, List data) { foreach (SqlData item in schema) { item.Values = data[schema.IndexOf(item)]; } return schema }