Sunday, May 1, 2011

List<> Get Next element or get the first

I want to get the next element in a list and if the list is at it's end I want the first element. So I just want it to circle in other words.

               List<int> agents = taskdal.GetOfficeAgents(Branches.aarhusBranch);
                if (lastAgentIDAarhus != -1)
                {
                    int index = agents.IndexOf(lastAgentIDAarhus);
                    if (agents.Count > index + 1)
                    {
                        lastAgentIDAarhus = agents[index + 1];
                    }
                    else
                    {
                        lastAgentIDAarhus = agents[0];
                    }
                }
                else
                {
                    lastAgentIDAarhus = agents[0];
                }

I am fairly displeased with my own solution shown above, let me know if you have a better one :)

From stackoverflow
  • Not a great difference, but at least some less code (at least in the editor) ;o)

    List<int> agents = taskdal.GetOfficeAgents(Branches.aarhusBranch);
    if (lastAgentIDAarhus != -1)
    {
        int index = agents.IndexOf(lastAgentIDAarhus);
        lastAgentIDAarhus = (agents.Count > index + 1 ? agents[index + 1] : agents[0]); 
    }
    else
    {
        lastAgentIDAarhus = agents[0];
    }
    
  • lastAgentIDAarhus = agents[ index == -1 ? 0 : index % ( agents.Count - 1 ) ];
    

    The use of the MOD operator % atuomatically chops the index to the range of possible indexes.

    The modulo operator is the compliment to the DIV (/) operator and returns the remainder of a division of two whole numbers. For example if you divide 9 by 6 the result is 1 with a remainder of 3. The MOD operator asks for the 3.

    The real napster : wow that is an extremely neat solution if that works :) care to explain it a bit?
    configurator : the mod operator does a modulo, which is exactly what you wanted. If you could initialize the index to 0 instead of -1, you could use: lastAgentIDAarhus = agents[index % (agents.Count - 1)]
  • As a slightly different take on this, here's an extension method you could use to make any IEnumerable 'circular'

      public static IEnumerable<T> AsCircularEnumerable<T>(this IEnumerable<T> enumerable)
      {
        var enumerator = enumerable.GetEnumerator();
        if(!enumerator.MoveNext())
          yield break;
    
        while (true)
        {
          yield return enumerator.Current;
          if(!enumerator.MoveNext())
            enumerator = enumerable.GetEnumerator();
        }
      }
    

    so you could use that like this

      var agents = new List<int> {1, 2, 3, 4, 123, 234, 345, 546};
    
      foreach(var i in agents.AsCircularEnumerable())
      {
        Console.WriteLine(i);
      }
    

    Which will just keep going... :)

0 comments:

Post a Comment