使用的foreach通过多个列表(语法糖)同时迭代 [英] using foreach to iterate simultaneously through multiple lists (syntax sugar)

查看:151
本文介绍了使用的foreach通过多个列表(语法糖)同时迭代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,有没有办法做这样的事情:

 的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这样的凯伊字类的东西 所以我想确定建立迭代器像<一个href="http://msdn.microsoft.com/de-de/library/system.threading.tasks.parallel.foreach.aspx">Parallel.ForEach做的ForEach&LT; TSource&GT;(IEnumerable的&LT; TSource&gt;中动作&LT; TSource&GT;) 但她的我得到stucked,因为我不知道如何实现它

  Static.ForEach&LT; TSource&GT;(IEnumerable的&LT; TSource&GT;,IEnumerable的&LT; TSource&gt;中???动作&LT; TSource,???&GT; ????)
 

解决方案

您可以做什么的foreach 引擎盖下做,但是有两个调查员:

 使用(VAR E1 = list1.GetEnumerator())
使用(VAR E2 = list2.GetEnumerator())
{
    而(e1.MoveNext()&安培;&安培; e2.MoveNext())
    {
         VAR ITEM1 = e1.Current;
         VAR项目2 = e2.Current;

         //使用ITEM1和ITEM2
    }
}
 

为了方便起见,你可以写这样采取行动以下的扩展方法:

 公共静态无效ZipDo&LT; T1,T2&GT;(这IEnumerable的&LT; T1&gt;首先,IEnumerable的&LT; T2&gt;第二个,动作&LT; T1,T2&GT;动作)
{
    使用(VAR E1 = first.GetEnumerator())
    使用(VAR E2 = second.GetEnumerator())
    {
        而(e1.MoveNext()&安培;&安培; e2.MoveNext())
        {
            行动(e1.Current,e2.Current);
        }
    }
}
 

和使用它像:

  list1.ZipDo(list2中,(I1,I2)=&GT; i1.Use(I2));
 


顺便说一句,你可以扩展为使用3个或更多列表:

 公共静态无效ZipDo&LT; T1,T2,T3&GT;(这IEnumerable的&LT; T1&gt;首先,
    IEnumerable的&LT; T2&GT;第二,IEnumerable的&LT; T3&GT;第三,
    动作&LT; T1,T2,T3&GT;行动)
{
    使用(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&GT; S:

 公共静态无效ZipAll&LT; T&GT;(这IEnumerable的&LT; IEnumerable的&LT; T&GT;&GT;全部动作&LT; IEnumerable的&LT; T&GT;&GT;动作)
{
    VAR枚举= all.Select(E =&GT; e.GetEnumerator())。了ToList();
    尝试
    {
        而(enumerators.All(E =&GT; e.MoveNext()))
            行动(enumerators.Select(E =&GT; e.Current));
    }
    最后
    {
        的foreach(在调查员变种E)
            e.Dispose();
    }
}
 

和使用它:

  VAR名单=新的[] {
     新[] {1,1,1},
     新的[] {2,2,2},
     新[] {3,3,3}};

lists.ZipAll(NUMS =&GT; 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);
}

EDIT

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

这篇关于使用的foreach通过多个列表(语法糖)同时迭代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆