您好,有没有办法做这样的事情:
的for(int i = 0; I< Math.Min(a.Count,b.Count);我++)
{
//做的东西
// A [1]
//双]
}
用foreach?
,因为这将是很好写的东西像
(/ * ...... * / List1中和VAR项目2在list2中VAR ITEM1) 的foreach
{
item1.use(ITEM2);
}
OK对不起,我不太清楚的一些人,所以我在这里希望能更好的解释
名单,其中,CLASSA>为listA = fillListA();
名单< CLASSB>数组listB = fillListB();
//这里可以是无穷大很多,有时不同势性的T型名单
现在我想执行某种的ForEach ,因为我不喜欢用的的循环做 它应该是简单明了以及像
(/ *和... *的/ var item1的List1中和VAR ITEM2在list2中) 的foreach
{
item1.use(ITEM2);
}
AFAIK我不能modifie这样的凯伊字类的东西
所以我想确定建立迭代器像Parallel.ForEach做的ForEach< TSource>(IEnumerable的< TSource>中动作< TSource>)
但她的我得到stucked,因为我不知道如何实现它
Static.ForEach< TSource>(IEnumerable的< TSource>,IEnumerable的< TSource>中???动作< TSource,???> ????)
解决方案
您可以做什么的foreach
引擎盖下做,但是有两个调查员:
使用(VAR E1 = list1.GetEnumerator())
使用(VAR E2 = list2.GetEnumerator())
{
而(e1.MoveNext()&安培;&安培; e2.MoveNext())
{
VAR ITEM1 = e1.Current;
VAR项目2 = e2.Current;
//使用ITEM1和ITEM2
}
}
为了方便起见,你可以写这样采取行动以下的扩展方法:
公共静态无效ZipDo< T1,T2>(这IEnumerable的< T1>首先,IEnumerable的< T2>第二个,动作< T1,T2>动作)
{
使用(VAR E1 = first.GetEnumerator())
使用(VAR E2 = second.GetEnumerator())
{
而(e1.MoveNext()&安培;&安培; e2.MoveNext())
{
行动(e1.Current,e2.Current);
}
}
}
和使用它像:
list1.ZipDo(list2中,(I1,I2)=> i1.Use(I2));
顺便说一句,你可以扩展为使用3个或更多列表:
公共静态无效ZipDo< T1,T2,T3>(这IEnumerable的< T1>首先,
IEnumerable的< T2>第二,IEnumerable的< T3>第三,
动作< T1,T2,T3>行动)
{
使用(VAR E1 = first.GetEnumerator())
使用(VAR E2 = second.GetEnumerator())
使用(VAR E3 = third.GetEnumerator())
{
而(e1.MoveNext()&安培;&安培; e2.MoveNext()&安培;&安培; e3.MoveNext())
{
行动(e1.Current,e2.Current,e3.Current);
}
}
}
上面的方法时,需要集合具有的不同的的泛型类型。但是,如果它们都具有的一样的泛型类型,那么你可以写一个灵活的方法,它采用任何数量的的IEnumerable&LT的; T>
S:
公共静态无效ZipAll< T>(这IEnumerable的< IEnumerable的< T>>全部动作< IEnumerable的< T>>动作)
{
VAR枚举= all.Select(E => e.GetEnumerator())。了ToList();
尝试
{
而(enumerators.All(E => e.MoveNext()))
行动(enumerators.Select(E => e.Current));
}
最后
{
的foreach(在调查员变种E)
e.Dispose();
}
}
和使用它:
VAR名单=新的[] {
新[] {1,1,1},
新的[] {2,2,2},
新[] {3,3,3}};
lists.ZipAll(NUMS => Console.WriteLine(nums.Sum()));
// 6
// 6
// 6
Hi is there a way to do things like this:
for (int i = 0; i < Math.Min(a.Count, b.Count); i++)
{
// Do stuff
//a[i]
//b[i]
}
with Foreach?
because it would be nice to write something like
foreach(var item1 in list1 and var item2 in list2 /* ....*/)
{
item1.use(item2);
}
ok sorry i wasn't clear enough for some people so here am hopefully better explanation
List<classA> listA = fillListA();
List<classB> listB = fillListB();
//here could be infinity many lists of sometimes diffrent T types
Now i want to perform some sort of ForEach because i dont like to do it with a for loop it should be simple and clear well something like
foreach(var item1 in list1 and var item2 in list2 /* and ...*/)
{
item1.use(item2);
}
AFAIK i cant modifie such a keay word class thing
so i thought ok build the iterator like Parallel.ForEach did ForEach<TSource>(IEnumerable<TSource>, Action<TSource>)
but her i get stucked because i don't know how implement it
Static.ForEach<TSource>(IEnumerable<TSource>,IEnumerable<TSource>, ???Action<TSource,???>????)
解决方案
You can do what foreach
does under the hood, but with two enumerators:
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
}
}
For convenience, you can write an extension method like the following that takes an action:
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);
}
}
}
and use it like:
list1.ZipDo(list2, (i1,i2) => i1.Use(i2));
By the way, you can expand this to use 3 or more lists:
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);
}
}
}
The approach above is required when the collections have different generic types. However, if they all have the same generic type, then you can write a flexible method that takes any number of IEnumerable<T>
s:
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();
}
}
and use it:
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