[英]using foreach to iterate simultaneously through multiple lists (syntax sugar)
嗨,有一種方法可以執行以下操作:
for (int i = 0; i < Math.Min(a.Count, b.Count); i++)
{
// Do stuff
//a[i]
//b[i]
}
與Foreach?
因為寫這樣的東西會很好
foreach(var item1 in list1 and var item2 in list2 /* ....*/)
{
item1.use(item2);
}
好的,抱歉,我對某些人還不夠清楚,因此希望這里有更好的解釋
List<classA> listA = fillListA();
List<classB> listB = fillListB();
//here could be infinity many lists of sometimes diffrent T types
現在我想執行某種形式的ForEach,因為我不喜歡使用for循環來完成它,它應該簡單明了,就像
foreach(var item1 in list1 and var item2 in list2 /* and ...*/)
{
item1.use(item2);
}
據我所知,我不能modifie這樣的凱伊字類的東西,所以我想確定建立一個像迭代器Parallel.ForEach做ForEach<TSource>(IEnumerable<TSource>, Action<TSource>)
但她我得到stucked,因為我不知道如何實現它
Static.ForEach<TSource>(IEnumerable<TSource>,IEnumerable<TSource>, ???Action<TSource,???>????)
您可以執行foreach
的幕后工作,但是有兩個枚舉器:
using(var e1 = list1.GetEnumerator())
using(var e2 = list2.GetEnumerator())
{
while(e1.MoveNext() && e2.MoveNext())
{
var item1 = e1.Current;
var item2 = e2.Current;
// use item1 and item2
}
}
為了方便起見,您可以編寫如下所示的擴展方法來執行操作:
public static void ZipDo<T1, T2>( this IEnumerable<T1> first, IEnumerable<T2> second, Action<T1, T2> action)
{
using (var e1 = first.GetEnumerator())
using (var e2 = second.GetEnumerator())
{
while (e1.MoveNext() && e2.MoveNext())
{
action(e1.Current, e2.Current);
}
}
}
並像這樣使用它:
list1.ZipDo(list2, (i1,i2) => i1.Use(i2));
順便說一句,您可以將其擴展為使用3個或更多列表:
public static void ZipDo<T1, T2, T3>(this IEnumerable<T1> first,
IEnumerable<T2> second, IEnumerable<T3> third,
Action<T1, T2, T3> action)
{
using (var e1 = first.GetEnumerator())
using (var e2 = second.GetEnumerator())
using (var e3 = third.GetEnumerator())
{
while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext())
{
action(e1.Current, e2.Current, e3.Current);
}
}
}
當集合具有不同的泛型類型時,需要上述方法。 但是,如果它們都具有相同的泛型類型,則可以編寫一個靈活的方法,該方法采用任意數量的IEnumerable<T>
:
public static void ZipAll<T>(this IEnumerable<IEnumerable<T>> all, Action<IEnumerable<T>> action)
{
var enumerators = all.Select(e => e.GetEnumerator()).ToList();
try
{
while (enumerators.All(e => e.MoveNext()))
action(enumerators.Select(e => e.Current));
}
finally
{
foreach (var e in enumerators)
e.Dispose();
}
}
並使用它:
var lists = new[] {
new[]{ 1, 1, 1 },
new[]{ 2, 2, 2 },
new[]{ 3, 3, 3 }};
lists.ZipAll(nums => Console.WriteLine(nums.Sum()));
// 6
// 6
// 6
我唯一能想到的就是Enumerable.Zip
和元組 :
foreach(var tuple in list1.Zip(list2, Tuple.Create))
{
tuple.Item1.use(tuple.Item2);
}
當然,如果不是use
,而是use
非副作用方法,該方法從兩個元素中產生了第三個值,則可以執行以下操作:
var result = list1.Zip(list2, (item1, item2) => item1.ProduceObject(item2))
.ToList(); // if required
您可以使用Zip方法(盡管僅在.net 4及更高版本中可用)是這樣的嗎?
List<int> l4 = new List<int> { 1, 2, 3, 4 };
List<int> l5 = new List<int> { 5, 6, 7 };
var l4Andl5 = l4.Zip(l5, (l, m) => new { List1 = l, List2 = m });
foreach (var x in l4Andl5)
{
}
如果列表的長度相同,也可以只使用局部整數變量:
List<classA> listA = fillListA();
List<classB> listB = fillListB();
var i = 0;
foreach(var itemA in listA)
{
itemA.use(listB[i++]);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.