HasNext, or the like, for Dictionary iterator

S

sasha

Basically, I am iterating over KeyValue pair of Dictionary. I need
to call some function when there is no next element in the dictionary:
something like this:

foreach (KeyValuePair<int, Object> kvp in MyDictionary)
{
//....do something
if(There is no next element)
call some function

}

I don't want to directly use the iterators, how would suggest to
approach this problem?


Thanks
 
J

Jeroen Mostert

sasha said:
Basically, I am iterating over KeyValue pair of Dictionary. I need
to call some function when there is no next element in the dictionary:
something like this:

foreach (KeyValuePair<int, Object> kvp in MyDictionary)
{
//....do something
if(There is no next element)
call some function

}

I don't want to directly use the iterators, how would suggest to
approach this problem?
Directly use the iterator.

It's either that or become a Zen master and learn how to speak of things
without mentioning them.
 
P

puzzlecracker

There are lots of possibilities, some more efficient than others.  My  
preferred approach would be simply to restructure the loop so that you can  
perform that "last element" work outside the loop.  For some loops, this  
is very easy, but even in the worst-case you might wind up with something 
like this:

     KeyValuePair<int, object> kvpPrev = null;

     foreach (KeyValuePair<int, object> kvp in MyDictionary)
     {
         if (kvpPrev != null)
         {
            // do stuff
         }

         kvpPrev = kvp;
     }

     if (kvpPrev != null)
     {
         // do stuff, including stuff for the last element
     }

The pattern can be made simpler and more maintainable by creating an  
anonymous method that can be called in both places (so you only have to  
maintain one copy of the loop body):

     KeyValuePair<int, object> kvpPrev = null;
     Action<bool> actionLoop = delegate(bool fLast)
         {
             // do stuff

             if (fLast)
             {
                 // do stuff for last element
             }

             // do other stuff
         };

     foreach (KeyValuePair<int, object> kvp in MyDictionary)
     {
         if (kvpPrev != null)
         {
             kvpPrev(false);
         }

         kvpPrev = kvp;
     }

     if (kvpPrev != null)
     {
         kvpPrev(true);
     }

Other methods include keeping a counter and comparing it to the count of  
elements in the dictionary so you know when you're at the end, or even (as  
Jeroen suggests) go ahead and use the iterator directly.

Pete

Thanks Guys, I did something simpler in terms of complexity:

int totaPairs = 0;
foreach (KeyValuePair<int, object> kvp in MyDictionary)
{
if(++totalPairs==MyDictionary.Count)
{
//do something... MyDictionary doesn't change during
the iteration, hence count remains the same during the loop
execution.
}

}

Any issues with that in a single threaded environment where Dictionary
will not change?

Thanks
 
N

Nicholas Paldino [.NET/C# MVP]

KeyValuePair<TKey, TValue> is a structure, so any of the solutions that
use null as a marker isn't going to work without some reworking. I'd
recommend creating an iterator which converts from KeyValuePair<int, object>
to KeyValuePair<int, object>?:

// You might need to do some work in the lambda passed to Select.
IEnumerable<KeyValuePair<int, object>?> nullableKvps = MyDictionary.Select(x
=> x);

You could work it further to have a static extension method which will
convert IEnumerable<T> to an IEnumerable<T?> and then append the null
element at the end to serve as your (the OP's) "marker".
 
P

puzzlecracker

    KeyValuePair said:
use null as a marker isn't going to work without some reworking.  I'd
recommend creating an iterator which converts from KeyValuePair<int, object>
to KeyValuePair<int, object>?:

// You might need to do some work in the lambda passed to Select.
IEnumerable<KeyValuePair<int, object>?> nullableKvps = MyDictionary.Select(x
=> x);

    You could work it further to have a static extension method whichwill
convert IEnumerable<T> to an IEnumerable<T?> and then append the null
element at the end to serve as your (the OP's) "marker".

I would like to see how it can be implemented with Lambada and
extension methods. I am fairly new to these features... hope I am not
asking too much
thanks,
 
N

Nicholas Paldino [.NET/C# MVP]

Yes, I definitely didn't mean to imply it would be a great task. It is
simple enough.
 

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