3

I currently have a object called Week. A week is part of a Season object. the season can contain many weeks. What I want to do is find the position of my week (is it the first week in the season (so #1) or is it the second (so #2).

int i = 0;
        foreach ( var w in Season.Weeks.OrderBy(w => w.WeekStarts)){
            if(w.Id == Id){
                return i;
            }
            i+=1;
        }

At the moment this is what I have. I order the weeks in a second by there start date to make sure they are in the correct order. and I cycle through them until I find the week that matches the week I am currently looking at. and return the int that I have been counting up..

I feel there should be a easier linq way to do this as it feels pretty messy!

Steve
  • 2,881
  • 6
  • 36
  • 61

3 Answers3

5

If you prefer not to write a FindIndex extension method or load the sorted items into an array / list, you could use the overload of Select that provides the index of the item:

 return Season.Weeks
              .OrderBy(w => w.WeekStarts)
              .Select((week, index) => new { Week = week, Index = index })
              .First(a => a.Week.Id == Id)
              .Index;

If there's no guarantee that the specified Id will exist, use FirstOrDefault instead:

var weekIndexTuple = Season.Weeks
                           .OrderBy(w => w.WeekStarts)
                           .Select((week, index) => 
                                    new { Week = week, Index = index })
                           .FirstOrDefault(a => a.Week.Id == Id);

if(weekIndexTuple != null)
{
    return weekIndexTuple.Index;
}
else
{
   // I'm not sure how you want to continue in this case.
   ...      
}
Ani
  • 107,182
  • 23
  • 252
  • 300
2

Here are answers to a very similar question: How to get the index of an element in an IEnumerable?

A lot of the answers are very similar to the way you're already doing it. It could be a good idea to pull the logic out into an extension method for separation of concerns and for easier reuse. Here's Marc Gravell's code from the link above:

public static int IndexOf<T>(this IEnumerable<T> source, T value)
{
    int index = 0;
    var comparer = EqualityComparer<T>.Default; // or pass in as a parameter
    foreach (T item in source)
    {
        if (comparer.Equals(item, value)) return index;
        index++;
    }
    return -1;
}
Community
  • 1
  • 1
Joel Beckham
  • 17,608
  • 3
  • 32
  • 58
1

SLaks posted a neat extension method for IEnumerables that gives you a method to find the index from within LINQ calls themselves: How to get index using LINQ?

Community
  • 1
  • 1
Daniel DiPaolo
  • 53,439
  • 13
  • 112
  • 113