C# 使用foreach在多个列表中同时迭代(语法)
嗨,有没有这样的方法:C# 使用foreach在多个列表中同时迭代(语法),c#,.net,C#,.net,嗨,有没有这样的方法: for (int i = 0; i < Math.Min(a.Count, b.Count); i++) { // Do stuff //a[i] //b[i] } 编辑 好吧,对不起,我对一些人不够清楚,所以希望这里有更好的解释 List<classA> listA = fillListA(); List<classB> listB = fillListB(); //here could be infinity m
for (int i = 0; i < Math.Min(a.Count, b.Count); i++)
{
// Do stuff
//a[i]
//b[i]
}
编辑
好吧,对不起,我对一些人不够清楚,所以希望这里有更好的解释
List<classA> listA = fillListA();
List<classB> listB = fillListB();
//here could be infinity many lists of sometimes diffrent T types
恐怕我不能修改这样一个单词类的东西
所以我认为可以像didForEach(IEnumerable,Action)一样构建迭代器
但她说我被绊倒了,因为我不知道如何实施它
Static.ForEach<TSource>(IEnumerable<TSource>,IEnumerable<TSource>, ???Action<TSource,???>????)
Static.ForEach(IEnumerable,IEnumerable,?Action??)
我唯一能想到的是:
当然,如果我们没有使用
,而是使用了一种无副作用的方法,从两个元素中产生第三个值,那么您可以:
var result = list1.Zip(list2, (item1, item2) => item1.ProduceObject(item2))
.ToList(); // if required
您可以使用类似这样的方法(尽管仅在.NET4及更高版本中可用)
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 l4=新列表{1,2,3,4};
列表l5=新列表{5,6,7};
var l4Andl5=l4.Zip(l5,(l,m)=>new{List1=l,List2=m});
foreach(L4和L5中的变量x)
{
}
您可以做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);
}
}
}
顺便说一下,您可以将其展开以使用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);
}
}
}
如果列表长度相同,也可以简单地使用局部整数变量:
List<classA> listA = fillListA();
List<classB> listB = fillListB();
var i = 0;
foreach(var itemA in listA)
{
itemA.use(listB[i++]);
}
List listA=fillListA();
List listB=fillListB();
var i=0;
foreach(列表A中的var itemA)
{
itemA.use(listB[i++]);
}
因此无法创建某种类型的操作
?我认为有一种方法可以编写类似于Parallel.Foreach()
的东西,没有什么可以阻止您在这里使用Parallel.Foreach而不是Foreach语言。对不起,我遗漏了什么吗?不,我的意思是并行。Foreach您可以像Parallel.Foreach(list,item=>{//dostuff})一样编写它,其中第一个参数=ienum,第二个参数=action。所以我想我可以编写一个函数,比如StaticClass.ForEach(Ienum,Ienum,someaction??)
你的意思是:Parallel.ForEach(list1.Zip(list2,Tuple.Create),Tuple=>Tuple.Item1.use(Tuple.Item2))代码>请记住,这只是并行调用操作,而不是枚举源或将它们压缩在一起。公共静态void ForEach(IEnumerable source1,IEnumerable source2,Action body){ForEach(source1.Zip中的var tuple(source2,tuple.Create)){body(tuple.Item1,tuple.Item2);}
?不完全是因为类型(a)!=typeof(b)也可以存在一个列表c、d,…这里类型不重要,第二个列表可以是string类型。你的答案与Ani的答案相比有什么优势吗?@WiiMaxx你可以将这种方法扩展到3个或更多列表(请参见编辑),但如果你只需要压缩2个列表,它们大致相同——实际上没有性能或可读性差异。如果一个列表比另一个短呢?“iterrate不就到此为止了吗?”克里斯,对不起,我晚了才注意到你的问题。是的,它将停止迭代,这通常是您想要的,并且与Linq的Zip方法一致。但是,如果要继续,可以将“&&MoveNext”替换为“| | MoveNext”。然后,您需要决定对完成的枚举器的当前项使用什么,例如使用默认值(T)。
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));
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);
}
}
}
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
List<classA> listA = fillListA();
List<classB> listB = fillListB();
var i = 0;
foreach(var itemA in listA)
{
itemA.use(listB[i++]);
}