1

我想这真的很简单,只是涉及使用迭代器和 .MoveNext() 方法。

但是假设您正在遍历一个集合,您在集合上做了一些工作,但是根据每个“循环”中的某些条件,您可能必须抓取 2 个或更多项目并基本上跳过它们,这样您就不会在接下来循环它们.

例子:

foreach (Fish fish in ParcelOfFish)
{
    GiverPersonFish(fish);
}

在这里,我只是遍历 Fish 的集合并将它们传递给一个方法。有些鱼很小,所以我必须再给那个人一条,这样它就不会饿死。

foreach (Fish fish in ParcelOfFish)
{
    GiverPersonFish(fish);

    if (fish.IsSmall)
    {
        GiverPersonFish(ParcelOfFish.MoveNext()); // here I want to give him the next fish
    }
}

这将如何工作,以便我给出的第二条鱼不会在下一个循环中迭代?

同样为了使这个更棘手,一个人可能会得到一条大鱼和一条小鱼是不公平的,所以每当有一条小鱼时,我都不想从迭代中抓住另一条小鱼然后继续。

所以如果订单是

Small
Big
Big
Small
Big
Small

在第一个“循环”之后,他会得到两个小的(索引 0 和 3),它将像这样遍历其余部分:

Big
Big
Big
Small

编译器似乎不喜欢在迭代时像这样修改迭代。

4

5 回答 5

2

迭代,按照设计,并不意味着像这样工作。如果您需要更灵活的行为,您应该使用 for 循环。

于 2012-11-13T12:15:11.000 回答
1

其实可以通过Enumerator

using (var enumerator = ParcelOfFish.GetEnumerator())
{
    // Bla bla whatever you need, but remember the first call to .MoveNext();
    if (!enumerator.MoveNext())
            break;

    // Your actions here. MoveNext() is bool and proceeds to the new item.
    // Try using while (!condition) { } here.
}
于 2012-11-13T13:02:18.233 回答
1

不要使用 foreach 循环 ( foreach(Foo foo in bar)),而是使用普通的旧 for 循环 ( for(int i = 0; i < bar.Length; i++))。

这将使您可以执行以下操作:

for (int i = 0; i < ParcelOfFish.Length; i++)
{
    Fish fish = ParcelOfFish[i];
    GiverPersonFish(fish);

    if (fish.IsSmall && i+1 < ParcelOfFish.Length)
    {
        GiverPersonFish(ParcelOfFish[++i]); // give him the next fish
    }
}

使用 for 循环还可以让您在列表中查看另一条小鱼,将其交给此人,然后将其从列表中删除(这次假设 ParcelOfFish 是列表,而不是数组):

for (int i = 0; i < ParcelOfFish.Count; i++)
{
    Fish fish = ParcelOfFish[i];
    GiverPersonFish(fish);

    if (fish.IsSmall)
    {
        for (int j = i+1; j < ParcelOfFish.Count; j++)
        {
            Fish fish2 = ParcelOfFish[j];
            if (fish2.IsSmall)
            {
                GiverPersonFish(fish2); // give him the next small fish
                ParcelOfFish.RemoveAt(j);
                break;                    
        }
    }
}
于 2012-11-13T12:21:21.510 回答
1

我会改用队列。

var queue = new Queue<Fish>(ParcelOfFish);
while (queue.Count > 0)
{
    var fish = queue.Dequeue();

    if (fish.IsSmall && queue.Count > 0) 
    {
        var fish2 = queue.Dequeue();

        if (fish2.IsSmall)
            GiverPersonFish(fish); // give them the first small fish
        else
            queue.Enqueue(fish); // throw it back to the end of the queue

        GiverPersonFish(fish2);
    }
    else
        GiverPersonFish(fish);
}

也适用于堆栈。

于 2012-11-13T12:28:13.003 回答
0

尝试

Enumerator<Fish> enumerator = ParcelOfFish.GetEnumerator();
Queue<Fish> bigFishCache = new Queue<Fish>(){ };
Boolean smallFishSwitch = false;

while(enumerator.MoveNext())
{
    if(smallFishSwitch)
    {
        if(enumerator.Current == BigFish)
        {
             bigFishCache.Enqueue(enumerator.Current);
        }
        else
        {
             smallFishSwitch = false;
             GivePersonFish(enumerator.Current);
             ForEach(Fish fish in bigFishCache)
             {
                  GivePersonFish(fish);
             }
             bigFishCache.Clear();
        }
    }
    else
    {
        smallFishSwitch = enumerator.Current == SmallFish;
        GivePersonFish(enumerator.Current);
    }    
}
于 2012-11-13T12:35:17.010 回答