在C#中使用一个ForEach语句迭代两个List或Arrays
这只是一般的知识:
如果我有两个,让我们说, 列表 ,我想迭代两个相同的foreach循环,我们可以做到这一点?
编辑
为了澄清,我想这样做:
List<String> listA = new List<string> { "string", "string" }; List<String> listB = new List<string> { "string", "string" }; for(int i = 0; i < listA.Count; i++) listB[i] = listA[i];
但是用foreach =)
这被称为Zip操作,将在.NET 4中受支持。
这样,你就可以写下如下的东西:
var numbers = new [] { 1, 2, 3, 4 }; var words = new [] { "one", "two", "three", "four" }; var numbersAndWords = numbers.Zip(words, (n, w) => new { Number = n, Word = w }); foreach(var nw in numbersAndWords) { Console.WriteLine(nw.Number + nw.Word); }
作为具有命名字段的匿名types的替代方法,您还可以使用Tuple及其静态Tuple.Create助手来保存大括号:
foreach (var nw in numbers.Zip(words, Tuple.Create)) { Console.WriteLine(nw.Item1 + nw.Item2); }
如果你不想等.NET 4.0,你可以实现你自己的Zip方法。 下面的工作与.NET 2.0。 您可以根据您想要处理两种枚举(或列表)具有不同长度的情况来调整实现:这种方法会持续到较长枚举的末尾,从较短的枚举中返回缺less项的缺省值。
static IEnumerable<KeyValuePair<T, U>> Zip<T, U>(IEnumerable<T> first, IEnumerable<U> second) { IEnumerator<T> firstEnumerator = first.GetEnumerator(); IEnumerator<U> secondEnumerator = second.GetEnumerator(); while (firstEnumerator.MoveNext()) { if (secondEnumerator.MoveNext()) { yield return new KeyValuePair<T, U>(firstEnumerator.Current, secondEnumerator.Current); } else { yield return new KeyValuePair<T, U>(firstEnumerator.Current, default(U)); } } while (secondEnumerator.MoveNext()) { yield return new KeyValuePair<T, U>(default(T), secondEnumerator.Current); } } static void Test() { IList<string> names = new string[] { "one", "two", "three" }; IList<int> ids = new int[] { 1, 2, 3, 4 }; foreach (KeyValuePair<string, int> keyValuePair in ParallelEnumerate(names, ids)) { Console.WriteLine(keyValuePair.Key ?? "<null>" + " - " + keyValuePair.Value.ToString()); } }
你可以使用联合或Concat,前者删除重复,后者不
foreach (var item in List1.Union(List1)) { //TODO: Real code goes here } foreach (var item in List1.Concat(List1)) { //TODO: Real code goes here }
这是一个自定义IEnumerable <>扩展方法,可以用来同时循环两个列表。
using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApplication1 { public static class LinqCombinedSort { public static void Test() { var a = new[] {'a', 'b', 'c', 'd', 'e', 'f'}; var b = new[] {3, 2, 1, 6, 5, 4}; var sorted = from ab in a.Combine(b) orderby ab.Second select ab.First; foreach(char c in sorted) { Console.WriteLine(c); } } public static IEnumerable<Pair<TFirst, TSecond>> Combine<TFirst, TSecond>(this IEnumerable<TFirst> s1, IEnumerable<TSecond> s2) { using (var e1 = s1.GetEnumerator()) using (var e2 = s2.GetEnumerator()) { while (e1.MoveNext() && e2.MoveNext()) { yield return new Pair<TFirst, TSecond>(e1.Current, e2.Current); } } } } public class Pair<TFirst, TSecond> { private readonly TFirst _first; private readonly TSecond _second; private int _hashCode; public Pair(TFirst first, TSecond second) { _first = first; _second = second; } public TFirst First { get { return _first; } } public TSecond Second { get { return _second; } } public override int GetHashCode() { if (_hashCode == 0) { _hashCode = (ReferenceEquals(_first, null) ? 213 : _first.GetHashCode())*37 + (ReferenceEquals(_second, null) ? 213 : _second.GetHashCode()); } return _hashCode; } public override bool Equals(object obj) { var other = obj as Pair<TFirst, TSecond>; if (other == null) { return false; } return Equals(_first, other._first) && Equals(_second, other._second); } } }
如果列表具有相同的长度,则也可以简单地使用本地整数variables:
List<classA> listA = fillListA(); List<classB> listB = fillListB(); var i = 0; foreach(var itemA in listA) { Console.WriteLine(itemA + listB[i++]); }
我明白/希望名单有相同的长度:不,你唯一的赌注是循环的旧标准。
不,你将不得不使用for循环。
for (int i = 0; i < lst1.Count; i++) { //lst1[i]... //lst2[i]... }
你不能这样做
foreach (var objCurrent1 int lst1, var objCurrent2 in lst2) { //... }
如果你想要一个相应的元素,你可以做
Enumerable.Range(0, List1.Count).All(x => List1[x] == List2[x]);
如果每个项目都等于第二个列表中的相应项目,则返回true
如果这几乎不是你想要的,如果你详细阐述的话,这将有所帮助。
这种方法可以用于列表实现,可以作为扩展方法来实现。
public void TestMethod() { var first = new List<int> {1, 2, 3, 4, 5}; var second = new List<string> {"One", "Two", "Three", "Four", "Five"}; foreach(var value in this.Zip(first, second, (x, y) => new {Number = x, Text = y})) { Console.WriteLine("{0} - {1}",value.Number, value.Text); } } public IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(List<TFirst> first, List<TSecond> second, Func<TFirst, TSecond, TResult> selector) { if (first.Count != second.Count) throw new Exception(); for(var i = 0; i < first.Count; i++) { yield return selector.Invoke(first[i], second[i]); } }
从C#7开始,你可以使用元组…
int[] nums = { 1, 2, 3, 4 }; string[] words = { "one", "two", "three", "four" }; foreach (var tuple in nums.Zip(words, (x, y) => (x, y))) { Console.WriteLine($"{tuple.Item1}: {tuple.Item2}"); } // or... foreach (var tuple in nums.Zip(words, (x, y) => (Num: x, Word: y))) { Console.WriteLine($"{tuple.Num}: {tuple.Word}"); }