Connie DeCinko
Connie DeCinko

Reputation: 1036

If first dictionary item do this, else do that

I'm passing a SortedDictionary array to a function and I need to loop over the items in the dictionary. If it's the first item, do X, else for all other items in the dictionary, do Y.

SortedDictionary<string,int> eventsArray

Found this but it's not working:

foreach (var eventItem in eventsArray)
{
    if (eventsArray.Keys.First())
        item.firstStuff();

    else if (items.Last() == item)
        item.lastStuff();

    item.otherStuff();
}

Upvotes: 0

Views: 77

Answers (3)

Nicholas Carey
Nicholas Carey

Reputation: 74345

You can do something like this:

SortedDictionary<string,int> dict = new SortedDictionary<string,int>();
IEnumerator<KeyValuePair<string,int>> dictWalker = dict.GetEnumerator();
if ( !dictWalker.MoveNext() )
{
  ProcessFirstItem( dictWalker.Current ) ;
  while ( !dictWalker.MoveNext() )
  {
    ProcessOtherItems(dictWalker.Current) ;
  }
}

Or you could make it a generic LINQ extension, like this:

public static class Extensions
{

  public static IEnumerable<T> Apply<T>( this IEnumerable<T> sequence , Action<T> firstAction , Action<T> middleAction , Action<T> lastAction )
  {
    IEnumerator<T> visitor = sequence.GetEnumerator();
    bool           hasCurr = visitor.MoveNext() ;
    T              curr    = hasCurr ? visitor.Current : default(T) ;
    bool           hasNext = visitor.MoveNext() ;
    T              next    = hasNext ? visitor.Current : default(T) ;
    Action<T>      noop    = x => {} ;
    Action         advance = () => {
      hasCurr = hasNext ;
      curr    = next    ;
      hasNext = visitor.MoveNext();
      next    = hasNext ? visitor.Current : default(T) ;
    } ;

    firstAction  = firstAction  ?? noop ;
    middleAction = middleAction ?? noop ;
    lastAction   = lastAction   ?? noop ;

    if ( hasCurr )
    {
      firstAction(curr);
      yield return curr;
      advance();
    }

    while ( hasCurr && hasNext )
    {
      middleAction(curr) ;
      yield return curr;
      advance();
    }

    if ( hasCurr )
    {
      lastAction(curr);
      yield return curr;
      advance();
    }

    if ( hasCurr || hasNext ) { throw new InvalidOperationException("Well, this is embarassing now, isn't it?"); }

  }
}

Cheers!

Upvotes: 0

jsirr13
jsirr13

Reputation: 1002

Quality Catalyst tried to base a solution off your description. And since it's not clear whether you want behavior described in your description, or in the example you shared, here's a jab at what it seems like you are trying to accomplish in the example:

var firstItem = eventsArray.First();
var lastItem = eventsArray.Last();
foreach (var eventItem in eventsArray)
{
    if (eventItem.Key == firstItem.Key)
        item.firstStuff();
    else if (eventItem.Key == lastItem.Key)
        item.lastStuff();
    else
        item.otherStuff();
}

However it's very hard to discern what item is in this example, but because your eventItem is a string, I assume this is close to what you want.

Upvotes: 1

Quality Catalyst
Quality Catalyst

Reputation: 6795

You said:

If it's the first item, do X, else for all other items in the dictionary, do Y.

In this case you don't need to check for the last item. Try this: it is simple, readable and fast:

bool isFirstItem = true; // when we enter the loop we know we deal with the first item
foreach (var eventItem in eventsArray)
{
    if (isFirstItem)
    {
        item.firstStuff();
        isFirstItem = false; // next item we deal with is not the first item
    }
    else
        item.otherStuff();
}

Upvotes: 3

Related Questions