473,766 Members | 2,064 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Question about Iteration and forEach

I am looping through an iteration and I would like to test the next item but
if its not the one that I want how do I put it back so that when my foreach
continues it is in the next iteration?

Bill
Jun 12 '07 #1
9 4051
"news.microsoft .com" <bi*******@char ter.netwrote in message
news:uj******** ******@TK2MSFTN GP02.phx.gbl...
>I am looping through an iteration and I would like to test the next item
but if its not the one that I want how do I put it back so that when my
foreach continues it is in the next iteration?
I'm not sure what you mean by "put it back". Can you explain?
Jun 12 '07 #2
On Mon, 11 Jun 2007 19:50:40 -0700, news.microsoft. com
<bi*******@char ter.netwrote:
I am looping through an iteration and I would like to test the next item
but
if its not the one that I want how do I put it back so that when my
foreach
continues it is in the next iteration?
You can't. The "foreach" statement strictly enumerates one by one through
the collection.

If you want the ability to adjust your position within the enumeration,
you can usually just use a normal "for" loop with an index to access
individual items within the collection. Then you can adjust the index as
needed.

I will note that if you are truly enumerating a list, having a need to
look at a specific item and then as a result of that inspection reverse
course and go back to the previous item is generally a bad sign. It
either means that you're not really enumerating the items in the list, and
so enumeration semantics aren't appropriate, or you are enumerating the
list in a manner indicative of poor design.

Hopefully you're in the former case, and you really don't want a true
enumeration, but you should at least consider the possibility of the
latter case. :) For more specific advice, you'd have to post the code
for the actual loop you're talking about.

Pete
Jun 12 '07 #3
On Jun 11, 8:54 pm, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
wrote:
On Mon, 11 Jun 2007 19:50:40 -0700, news.microsoft. com

<billgo...@char ter.netwrote:
I am looping through an iteration and I would like to test the next item
but
if its not the one that I want how do I put it back so that when my
foreach
continues it is in the next iteration?
<snip sound advice :-) >
I will note that if you are truly enumerating a list, having a need to
look at a specific item and then as a result of that inspection reverse
course and go back to the previous item is generally a bad sign.
Oh, I don't know that I would be so harsh. A good old fashioned
"control-break" iteration is an example of this sort of thing: loop
through the invoices until the customer code changes, process
everything up to the preceding entry, then start with the one you read
last as the "next one" and proceed.

Of course, in a modern language it's often cleaner to build a new data
structure reflecting what you want to do (e.g. a list of customers,
each entry containing a list of invoices for that customer), but the
old way to solve the problem isn't really "bad design"... just
different.

As Peter said, though, it would be better to give us more details
about what you're trying to do, or even post the code. Perhaps we can
come up with a better design, or perhaps we'll reaffirm that what
you're doing is the best way.

Jun 12 '07 #4
On Mon, 11 Jun 2007 21:59:47 -0700, Bruce Wood <br*******@cana da.com
wrote:
>I will note that if you are truly enumerating a list, having a need to
look at a specific item and then as a result of that inspection reverse
course and go back to the previous item is generally a bad sign.

Oh, I don't know that I would be so harsh.
I thought I was being pretty open to the occasional exception, actually.
I think I could have been a LOT more harsh. :p
A good old fashioned
"control-break" iteration is an example of this sort of thing: loop
through the invoices until the customer code changes, process
everything up to the preceding entry, then start with the one you read
last as the "next one" and proceed.
Even absent a convenient way in the language to simply collect all of the
items of interest in a new data structure, what would be wrong with just
doing something like this:

int i = 0, count = items.Length;

while (i < count)
{
custid = items[i].custid;
while (i < count && items[i].custid == custid)
{
// process the item
i++;
}

// do whatever per-customer stuff here
}

If you don't like the nested loops:

int i = 0, count = items.Length;
int custid = items[i].custid;

while (i < count)
{
// process the item
i++;

if (i >= count || items[i].custid != custid)
{
// do whatever per-customer stuff here
}
}

IMHO, either of those is preferable to doing something with the loop index
other than just monotonically increasing it.

Note also that I'm not talking about peeking ahead in the enumeration,
though I think that's also almost never necessary. I'm talking about the
impression I got from the original post that the enumeration would
actually go *backwards* to an item already processed.
Of course, in a modern language it's often cleaner to build a new data
structure reflecting what you want to do (e.g. a list of customers,
each entry containing a list of invoices for that customer), but the
old way to solve the problem isn't really "bad design"... just
different.
I'm not willing to state unequivocably that it is _always_ wrong to modify
the loop counter in the loop other than simply increasing it. I figure,
any time one ever says something is absolute, there's always some joker
out there who's got the one incredibly esoteric counter-example. :) But
I still believe that doing so is generally a sign of poor design. It's
practically never necessary, and doing so makes the code harder to read,
harder to understand, and harder to maintain in a bug-free manner.

Pete
Jun 12 '07 #5
Never say you can't. We are programmers we can do anything!!!
Here is a sample.. It is probably not as simple as you would like. but it
does what you want.
I just defined a couple if interfaces; IPeakableEnumer ator<Tand
IPeakEnumerable <T>. I then created a collection that derives from List<T>
that implements the interfaces.
And viola. You now have a Peak() method on an enumerator that will get the
next element for you without moving to the next element.
public class Test
{
public static void DoTest()
{
MyList<stringa = new MyList<string>( );
a.Add("a");
a.Add("b");
a.Add("c");
a.Add("d");
a.Add("e");

IPeakableEnumer ator<stringen = a.GetPeakableEn umerator();
while (en.MoveNext())
{
Console.WriteLi ne(en.Current);
Console.WriteLi ne(en.Peak());
}
}
}

public interface IPeakableEnumer ator<T: IEnumerator<T>
{
T Peak();
}
public interface IPeakEnumerable <T>
{
IPeakableEnumer ator<TGetPeakab leEnumerator();
}
public class MyList<T: List<T>, IPeakEnumerable <T>
{
public IPeakableEnumer ator<TGetPeakab leEnumerator()
{
return new MyListEnumerato r(this);
}

[Serializable, StructLayout(La youtKind.Sequen tial)]
public class MyListEnumerato r : IPeakableEnumer ator<T>, IEnumerator<T>,
IDisposable, IEnumerator
{
private MyList<Tlist;
private int index;
private T current;
internal MyListEnumerato r(MyList<Tlist)
{
this.list = list;
this.index = 0;
this.current = default(T);
}

public void Dispose()
{
}

public bool MoveNext()
{
if (this.index < this.list.Count )
{
this.current = this.list[this.index];
this.index++;
return true;
}
this.index = this.list.Count + 1;
this.current = default(T);
return false;
}

public T Current
{
get
{
return this.current;
}
}
object IEnumerator.Cur rent
{
get
{
if ((this.index == 0) || (this.index == (this.list.Coun t +
1)))
{
throw new InvalidOperatio nException("Enu meration
failed");
}
return this.Current;
}
}
void IEnumerator.Res et()
{
this.index = 0;
}

public T Peak()
{
if (this.index >= this.list.Count )
{
return default(T);
}
return this.list[index];
}
}
}
Jeremy Shovan
http://www.jeremyshovan.com
"Peter Duniho" <Np*********@nn owslpianmk.comw rote in message
news:op******** *******@petes-computer.local. ..
On Mon, 11 Jun 2007 19:50:40 -0700, news.microsoft. com
<bi*******@char ter.netwrote:
>I am looping through an iteration and I would like to test the next item
but
if its not the one that I want how do I put it back so that when my
foreach
continues it is in the next iteration?

You can't. The "foreach" statement strictly enumerates one by one through
the collection.

If you want the ability to adjust your position within the enumeration,
you can usually just use a normal "for" loop with an index to access
individual items within the collection. Then you can adjust the index as
needed.

I will note that if you are truly enumerating a list, having a need to
look at a specific item and then as a result of that inspection reverse
course and go back to the previous item is generally a bad sign. It
either means that you're not really enumerating the items in the list, and
so enumeration semantics aren't appropriate, or you are enumerating the
list in a manner indicative of poor design.

Hopefully you're in the former case, and you really don't want a true
enumeration, but you should at least consider the possibility of the
latter case. :) For more specific advice, you'd have to post the code
for the actual loop you're talking about.

Pete
Jun 12 '07 #6
On Tue, 12 Jun 2007 00:48:01 -0700, Jeremy Shovan
<je***********@ student.neumont .eduwrote:
Never say you can't. We are programmers we can do anything!!!
Here is a sample.. It is probably not as simple as you would like. but
it does what you want.
A few thoughts:

1) If you're going to make a "peekable" enumerator, you should
probably spell the word "peek" correctly. At least, if you expect anyone
else to use it, anyway. :)
2) More seriously, you'll note that doing this you have to implement
the entire collection class yourself. There was nothing in the original
post that suggested he was looking to do that, nor is it clear to me that
doing so is always going to be feasible.
3) It's not at all clear to me that simply "peeking" at the next
element in the iteration would be sufficient for the original poster. I
got the impression he wanted to be able to actually move backwards in the
enumeration.
4) I note that the code you've provided doesn't actually use the
"foreach" statement. Again, there seems to be a disconnect between the
original question and the solution you've offered. :)
5) Finally, while I admire your dedication to the problem, it seemsto
me that it would be simpler to simply emulate a "peekable" enumerator
through something like this (assuming, of course, that being able to
"peek" ahead would suffice for the OP's needs):

Item itemPrev = null;

foreach (Item itemCur in MyCollection)
{
if (itemPrev != null)
{
// Do some stuff with itemPrev.
// If we want to "peek" at the next one, look at itemCur
}

itemPrev = itemCur;
}

// Finish up by doing stuff with itemPrev here too. No peeking
allowed!

Note that the above works with any class that implements IEnumerable,
which IMHO would be a major benefit over requiring one's collection class
to be entirely redefined just to support that one aspect of the operation.

My two cents. :)

Pete
Jun 12 '07 #7
Not want to get in a coding contest but you can also encapsulate this in
an iterator (.Net 2). This way you can reuse the idiom for any
Enumerable collection and it allows you to create almost any traversal
you like or even create collections on the fly.

// Class that will be the return type of the iterator, contains
// the current value and the next 'peeked' value.
class Pair<T>
{
public Pair (T first, T second)
{
Current = first;
Next = second;
}

public T Current;
public T Next;
}

// Defined in some class (unrelated to the collection, maybe a
// static class collecting different iterators :-))
static IEnumerable<Pai r<T>peeking_ite rator<T(IEnumer able<Tcoll)
{
IEnumerator<Tit = coll.GetEnumera tor ();
T first = default(T);

// Get the first element and remember it.
if (it.MoveNext ())
first = it.Current;

// Loop through all elements
while (it.MoveNext ())
{
// Return a pair of the current element and the next element
yield return new Pair<T(first, it.Current);

first = it.Current;
}

// When necessary return the last element BUT the 'next' element
// will have the default value: 0 for value types like int or
// null for objects.
yield return new Pair<T(first, default (T));
}

// Test the iterator
public static void tst_iterator ()
{
int[] tstints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

// Note here how the custom iterator is used to wrap
// any IEnumerable collection in a foreach statement.

foreach (Pair<intp in peeking_iterato r (tstints))
{
System.Diagnost ics.Debug.Write Line (
string.Format ("pair: {0}, {1}", p.Current, p.Next));
}

string[] tststrings = new string[] { "abc", "def", "ghi" };

foreach (Pair<stringp in peeking_iterato r (tststrings))
{
System.Diagnost ics.Debug.Write Line (
string.Format ("pair: {0}, {1}", p.Current, p.Next));
}
}

Peter Duniho wrote:
[snip]
Item itemPrev = null;

foreach (Item itemCur in MyCollection)
{
if (itemPrev != null)
{
// Do some stuff with itemPrev.
// If we want to "peek" at the next one, look at itemCur
}

itemPrev = itemCur;
}
Jun 12 '07 #8
I’m sorry, I didn't mean to offend you! But.

1) If you're going to make a "peekable" enumerator, you should probably
spell the word "peek" correctly. At least, if you expect anyone else to use
it, anyway. :)

--- I will give you this one. But I did write this at 2:00 in the morning.

2) More seriously, you'll note that doing this you have to implement
the entire collection class yourself. There was nothing in the original
post that suggested he was looking to do that, nor is it clear to me that
doing so is always going to be feasible.

--- I did not implement the entire collection

public class MyList<T: List<T>, IPeakEnumerable <T>
{
public IPeakableEnumer ator<TGetPeakab leEnumerator()
{
return new MyListEnumerato r(this);
}
This is hardly the entire collection. This is what we call inheritance.
I did however implement the enumerator as an inner class. But that really is
not a lot of code.

3) It's not at all clear to me that simply "peeking" at the next
element in the iteration would be sufficient for the original poster. I got
the impression he wanted to be able to actually move backwards in the
enumeration.

--- The original poster said "I would like to test the next item but if it’s
not the one that I want how do I put it back so that when my foreach
continues it is in the next iteration".

The key parts to this sentence are:
- "I would like to test the next item
- when my foreach continues it is in the next iteration.

My implementation supports exactly this.

4) I note that the code you've provided doesn't actually use the
"foreach" statement. Again, there seems to be a disconnect between the
original question and the solution you've offered. :)

--- Whether you use a 'while' or a 'foreach' you are still enumerating
through the collection. It really doesn't matter which one you use. There is
nothing saying that you must use a foreach rather than a while.

Also, if you used my implementation in a foreach then you would still be
returned an IEnumerator and that is not the type that I want with my
solution. I want an IPeekableEnumer ator

5) Finally, while I admire your dedication to the problem, it seems to
me that it would be simpler to simply emulate a "peekable" enumerator
through something like this (assuming, of course, that being able to "peek"
ahead would suffice for the OP's needs):

--- If you did this it wouldn't be an enumerator, now would it?
Lastly, if you spent this much effort trying to actually come up with
solutions rather than knocking others for actually trying to solve a problem
you would be much more useful and much more liked. Though my solution is not
as good as the one Freddy Potargent provided, at least it is a solution.


"Peter Duniho" <Np*********@nn owslpianmk.comw rote in message
news:op******** *******@petes-computer.local. ..
On Tue, 12 Jun 2007 00:48:01 -0700, Jeremy Shovan
<je***********@ student.neumont .eduwrote:
Never say you can't. We are programmers we can do anything!!!
Here is a sample.. It is probably not as simple as you would like. but it
does what you want.
A few thoughts:

1) If you're going to make a "peekable" enumerator, you should
probably spell the word "peek" correctly. At least, if you expect anyone
else to use it, anyway. :)
2) More seriously, you'll note that doing this you have to implement
the entire collection class yourself. There was nothing in the original
post that suggested he was looking to do that, nor is it clear to me that
doing so is always going to be feasible.
3) It's not at all clear to me that simply "peeking" at the next
element in the iteration would be sufficient for the original poster. I
got the impression he wanted to be able to actually move backwards in the
enumeration.
4) I note that the code you've provided doesn't actually use the
"foreach" statement. Again, there seems to be a disconnect between the
original question and the solution you've offered. :)
5) Finally, while I admire your dedication to the problem, it seems to
me that it would be simpler to simply emulate a "peekable" enumerator
through something like this (assuming, of course, that being able to
"peek" ahead would suffice for the OP's needs):

Item itemPrev = null;

foreach (Item itemCur in MyCollection)
{
if (itemPrev != null)
{
// Do some stuff with itemPrev.
// If we want to "peek" at the next one, look at itemCur
}

itemPrev = itemCur;
}

// Finish up by doing stuff with itemPrev here too. No peeking
allowed!

Note that the above works with any class that implements IEnumerable,
which IMHO would be a major benefit over requiring one's collection class
to be entirely redefined just to support that one aspect of the operation.

My two cents. :)

Pete

Jun 12 '07 #9
On Tue, 12 Jun 2007 08:55:06 -0700, Jeremy Shovan
<je***********@ student.neumont .eduwrote:
I’m sorry, I didn't mean to offend you! But.
You didn't offend me. I have no idea why you think you did.
[...]
2) More seriously, you'll note that doing this you have to
implement the entire collection class yourself. There was nothing in
the original post that suggested he was looking to do that, nor is it
clear to me that doing so is always going to be feasible.

--- I did not implement the entire collection
Poor choice of words on my part. My point is that your method requires a
whole new type.
[...]
3) It's not at all clear to me that simply "peeking" at the next
element in the iteration would be sufficient for the original poster. I
got the impression he wanted to be able to actually move backwards in
the enumeration.

--- The original poster said "I would like to test the next item but if
it’s not the one that I want how do I put it back so that when my
foreach continues it is in the next iteration".

The key parts to this sentence are:
- "I would like to test the next item
- when my foreach continues it is in the next iteration.
Well, I admit that there's ambiguity there. But don't agree that your
interpretation is a foregone conclusion. That's why I wrote "it's not at
all clear". Note that I did not write "that's not what the OP wants". I
simply pointed out that your solution may or may not be the one he wants
or needs.
[...]
--- Whether you use a 'while' or a 'foreach' you are still enumerating
through the collection. It really doesn't matter which one you use.
There is nothing saying that you must use a foreach rather than a while.
You mean, other than the fact that the OP says he wants to use "foreach".
Other than that, you mean. Right?
Also, if you used my implementation in a foreach then you would still be
returned an IEnumerator and that is not the type that I want with my
solution. I want an IPeekableEnumer ator
That's my point. Your solution is not compatible with the basic "foreach"
statement. When the OP says he wants to use "foreach".
5) Finally, while I admire your dedication to the problem, it seems
to me that it would be simpler to simply emulate a "peekable" enumerator
through something like this (assuming, of course, that being able to
"peek" ahead would suffice for the OP's needs):

--- If you did this it wouldn't be an enumerator, now would it?
The OP didn't ask about having an enumerator. He _did_ ask about using
the "foreach" statement. Which do you suppose is the approach more likely
to meet the OP's request?
Lastly, if you spent this much effort trying to actually come up with
solutions rather than knocking others for actually trying to solve a
problem you would be much more useful and much more liked. Though my
solution is not as good as the one Freddy Potargent provided, at least
it is a solution.
Now, here...you are _completely_ off-base. I think you'll find that I
spend plenty of time offering solutions to others, and in fact very little
of my time is spent "knocking others for actually trying". Note also that
I did NOT "knock" you for trying. I knocked you for offering a solution
that was not, IMHO, all that appropriate or practical. In fact, I
commended you for trying.

So, whatever else you think of my reply, you are absolutely, completely
wrong to characterize it as simply "knocking you for trying", and
absolutely, completely wrong in accusing me of failing to provide
solutions myself.

Pete
Jun 12 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
1996
by: NewsHound | last post by:
I've been playing around with Perl for a while, but I'm still something of a beginner. I was wondering what happens in the following case. Take a "foreach" loop iterating through the sorted keys of a hash: foreach $key (sort keys %hash) { # do stuff here } Does the "sort" function re-sort the keys before each iteration of the "foreach" loop? I was wondering if it is possible to insert additional
7
1335
by: billr | last post by:
but ireally does need clearing up ... Traditionally (i.e. in C++) I might do the following: SomeObj ptrSomeObj; for(int i = 0; i < iCount; ++i) { ptrSomeObj = new SomeObj(); ptrSomeObj->MethodOne(); delete ptrSomeObj;
2
988
by: Ray5531 | last post by:
what is the equivalent of this in C# ? foreach (XmlNode xmlConfigNode in xmlConfigDoc.ChildNodes) Thansk
15
1365
by: MuZZy | last post by:
Hi, Consider this: ArrayList al = new ArrayList(); FillList(al); /// NOW TWO SCENARIOS: /// 1. for (int i = 0 ; i < al.Count ; i++)
2
8794
by: Bob | last post by:
Hi, I have a list of widgets. I want to iterate through the selected items collection and modify one of the widgets properties. I tried foreach(widget w in lst.SelectedItems) w.MyProperty = something; but I get a message saying "Cannot modify members of w because it is a foreach iteration variable" What is the point of iteration if you can't modify the objects?
4
22253
by: bg_ie | last post by:
Hi, What is wrong with the following - short arrfile = new short; foreach (short s in arrfile) { s = 10; }
2
19903
by: John Kelsey | last post by:
I am an old, longtime C programmer surprised and confused by an error message I'm getting from my VS2005 compiler... "Cannot pass 'Item' as a ref or out argument because it is a 'foreach iteration variable'" is the error message I'm getting for code that I think should work. I'm sure that there is some sublety I'm missing... maybe with the use of a reference, or foreach, or template class. Can someone maybe explain it with small words...
11
1611
by: SM | last post by:
I have a couple of arrays that represent different categories. One array per category. The arrays contain names of photos. The arrays look like this: $cat_1 = array('moonlight.jpg'', shadow.jpg', 'luna.jpg'); $cat_2 = array(...); $cat_3 = array(...); $cat_4 = array(...); Then, i want to create a thumbnail with all the photos like this:
1
3367
by: greyseal96 | last post by:
Hi, I am a pretty new programmer, so I apologize in andvance if this is a dumb question... In a book that I'm reading to learn C#, it says that when using a foreach() loop, a read-only copy of the iteration variable is used and you cannot modify it. For example: int pins = {9, 3, 7, 2} int newPin = 10; foreach(int pin in pins) {
0
9568
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10168
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9959
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9837
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7381
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5279
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5423
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3532
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2806
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.