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,971
  • 7
  • 38
  • 63

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
  • 111,048
  • 26
  • 262
  • 307
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
  • 18,254
  • 3
  • 35
  • 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
  • 55,313
  • 14
  • 116
  • 115