Reset a foreach loop.

K

Ken Varn

Is there any way to reset a foreach loop to re-iterate through the
collection as if it were starting from the beginning? Namely, if I delete
an item out of a collection, I want to be able to reset the loop.

--
-----------------------------------
Ken Varn
Senior Software Engineer
Diebold Inc.

EmailID = varnk
Domain = Diebold.com
-----------------------------------
 
C

Chad Z. Hower aka Kudzu

Ken Varn said:
Is there any way to reset a foreach loop to re-iterate through the
collection as if it were starting from the beginning? Namely, if I
delete an item out of a collection, I want to be able to reset the
loop.

No, you need to use a for loop or a while loop.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Empower ASP.NET with IntraWeb
http://www.atozed.com/IntraWeb/
 
M

Michael Rodriguez

Ken Varn said:
Is there any way to reset a foreach loop to re-iterate through the
collection as if it were starting from the beginning? Namely, if I delete
an item out of a collection, I want to be able to reset the loop.

I have to say I disagree with a for loop that iterates through a collection
and then changes the collection in the loop. However if you must do it,
wrap the for loop inside of a while loop (while (1=1)) that doesn't end.

while (1==1)
{
foreach (...)
{
if (item_deleted_from_collection)
{
item_deleted = true;
break;
}
}
if (not item_deleted)
break;
}

HTH,

Mike Rodriguez
 
J

J.Marsch

Just curious, what is the end result that you are trying to accomplish?
Perhaps there is a better way.
 
M

Michael C

Ken Varn said:
Is there any way to reset a foreach loop to re-iterate through the
collection as if it were starting from the beginning? Namely, if I delete
an item out of a collection, I want to be able to reset the loop.

It's possibly better to go backwards through the collection in a normal for
loop and remove items as necessary.

Why do you need to start over completely, if you remove an item couldn't you
still continue on?

Michael
 
J

J.Marsch

That's what I was getting at as well, also, in the default enumerator
implementations, don't you get an exception when you modify a collection
that you are enumerating with foreach?
 
F

Fred Mellender

I don't believe you can reset the foreach loop inside the loop, or continue
after you have modified the collection. About the best you can do is:

bool more = true;
while (collect.Count > 0 && more)
{
more = false;
foreach (Typ t in collect)
{
if (something)
{
collect.Remove(t);
more = true;
break;
}
}
}

or words to that effect <G>.
 
J

Jon Skeet [C# MVP]

James Curran said:
Goto are evil, and renaming a goto doesn't make it any less evil,
particular when there's no reason for it in your code:

Personally I don't like do/while instead of just plain while:

while (keepGoing)
{
foreach (...)
{
if (item_deleted_from_collection)
{
keepGoing = false;
break;
}
}
}

I don't like to have to wait until the end of loop to find out how long
I'm going to have to run the loop for :)

Could be just me though...
 
B

Bill Butler

Jon Skeet said:
Personally I don't like do/while instead of just plain while:

while (keepGoing)
{
foreach (...)
{
if (item_deleted_from_collection)
{
keepGoing = false;
break;
}
}
}

I don't like to have to wait until the end of loop to find out how long
I'm going to have to run the loop for :)


I tend to prefer while/do as well
However, I think you have a logic error in your version. It stops after the
first delete.
How about:

bool keepGoing = false;
while (!keepGoing)
{
keepGoing = true;
foreach (...)
{
if (item_deleted_from_collection)
{
keepGoing = false;
break;
}
}
}

Bill
 
J

Jon Skeet [C# MVP]

Bill Butler said:
I tend to prefer while/do as well
However, I think you have a logic error in your version. It stops after the
first delete.
How about:

Sorry, yes, you're right. That just shows that I shouldn't post code
when ill :)
 
M

Maqsood Ahmed

Hello,
As far as I know, if you try to remove an item inside the foreach an
exception will occur as the enumerator gets corrupted for the foreach
loop.

HTH. Cheers :)
Maqsood Ahmed [MCP,C#]
Kolachi Advanced Technologies
http://www.kolachi.net
 
C

Chad Z. Hower aka Kudzu

Maqsood Ahmed said:
As far as I know, if you try to remove an item inside the foreach an
exception will occur as the enumerator gets corrupted for the foreach
loop.

It depends on how the enumerator is implemented, but I agree its not a wise thing to try.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Develop ASP.NET applications easier and in less time:
http://www.atozed.com/IntraWeb/
 
B

Bill Butler

Ken Varn said:
Is there any way to reset a foreach loop to re-iterate through the
collection as if it were starting from the beginning? Namely, if I delete
an item out of a collection, I want to be able to reset the loop.

Hi Ken,

So far we have all discussed various work-arounds to this issue.
Now, I would like to suggest that you take a different approach.

I call it "The Hit List" or "Death Row" and it works like this

----------- Pseudocode -----------
ArrayList HitList = new HitList();
foreach (Thing thing in YourCollection)
{
if (NeedsKilling(thing))
{
HitList.Add(thing);
}
else
{
Process(thing);
}
}
foreach(Thing victim in HitList)
{
YourCollection.Remove(victim);
}
-------------------------------------
Advantages
------------
This algorithm is O(n) as opposed to the others which were O(n^2).
You only loop through the collection once so you can do other processing as well.
------------

It would be nice to have something like remove_if() from the C++ STL.

Hope this helps
Bill
 
W

William Stacey [MVP]

IIRC, Remove iterates the list too until it finds the object. So you
iterate once for the hitlist and one for item in the hitlist. I would agree
this is probably the best way however.
 
W

William Stacey [MVP]

Here is another way to do it in one pass:

string[] sa = new string[]{"one", "one", "two", "one", "two",
"two", "three", "one"};
ArrayList al = new ArrayList(sa);
string sToDel = "one";
for ( int i = 0; i < al.Count; )
{
string s = (string)al;
if ( s == sToDel )
{
al.RemoveAt(i);
continue;
}
i++;
}
Console.WriteLine("List after removing item(s):");
foreach ( string s in al )
{
Console.WriteLine(s);
}
 
J

James Curran

Maqsood Ahmed said:
Hello,
As far as I know, if you try to remove an item inside the foreach an
exception will occur as the enumerator gets corrupted for the foreach
loop.

Deleting shouldn't cause the exception. Using the enumerator after a
deletion should. (i.e, you would need to exit the loop immedaitely after the
deletion)

--
--
Truth,
James Curran
[erstwhile VC++ MVP]

Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com
 
J

J.Marsch

FWIW:

If the order that you use to iterate the collection does not matter, you can
make it a little simpler by iterating the collection backwards:

string[] sa = new string[] {"one", "one", "two", "etc", "one", "etc"};
ArrayList al = new ArrayList(sa); // kind of contrived
string sToDel = "one";
for(int i = al.Count - 1; i >= 0; i--)
{
if(sToDel.Equals(al))
al.RemoveAt(i);
}


since you are counting down, the deletion does not affect the index of your
next test.

William Stacey said:
Here is another way to do it in one pass:

string[] sa = new string[]{"one", "one", "two", "one", "two",
"two", "three", "one"};
ArrayList al = new ArrayList(sa);
string sToDel = "one";
for ( int i = 0; i < al.Count; )
{
string s = (string)al;
if ( s == sToDel )
{
al.RemoveAt(i);
continue;
}
i++;
}
Console.WriteLine("List after removing item(s):");
foreach ( string s in al )
{
Console.WriteLine(s);
}

--
William Stacey [MVP]

William Stacey said:
IIRC, Remove iterates the list too until it finds the object. So you
iterate once for the hitlist and one for item in the hitlist. I would
agree this is probably the best way however.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top