LINQ gems: Indexed Select

jdoubek

Jan Doubek

Posted on October 28, 2020

LINQ gems: Indexed Select

Here's another LINQ gem, which is very useful if you plan to base your projection or filtering logic on the element's index in a sequence.

From the MSDN page for Enumerable.Select():

Projects each element of a sequence into a new form by incorporating the element's index.

What the "incorporating the element's index" part means is that you get an extra parameter inside of the Select method's selector, which gets incremented with each processed element. As is common in C#, the index is zero-based.

Example

Let's have a look at a simple example, which outputs the sequence numbers of days in a week (apologies to all readers, for whom Monday is not the first day of the week 😊).

var days = new[] { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
var daysOutput = days.Select((day, index) => 
    $"{day} is day number: {(index + 1)}").ToList();
daysOutput.ForEach(output => Console.WriteLine(output));
Enter fullscreen mode Exit fullscreen mode

When executed, the output will be the following:

Mon is day number: 1
Tue is day number: 2
Wed is day number: 3
Thu is day number: 4
Fri is day number: 5
Sat is day number: 6
Sun is day number: 7
Enter fullscreen mode Exit fullscreen mode

or...

Let's just simply generate a sequence number for an array of values and project it into an array for whatever usage may be appropriate.

var days = new[] { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
var indexedDays = days.Select((day, index) => 
    new { Day = day, Index = index }).ToArray();
Enter fullscreen mode Exit fullscreen mode

How about query expression syntax?

There is no query expression syntax for this overload of the Select method. However, one can simply embed the indexed Select overload inside of the query expression:

var days = new[] { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
var weekendDays = 
    from day in days.Select((day, index) => new { day, num = index + 1 })
    where day.num >= 6
    select day.day;
Enter fullscreen mode Exit fullscreen mode

Enumerable.Where()

There is an indexed overload available for the Enumerable.Where() extension method too. Using Where instead of Select, the previous example can be further simplified:

var days = new[] { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
var weekendDays = days.Where((day, index) => index >= 5); // (index+1) >= 6
Enter fullscreen mode Exit fullscreen mode

Other useful applications

  • Selecting each N-th element in a sequence

  • Ordering based on element position

  • Coordination across multiple sequences


If you find this post interesting, be sure to check out other posts on my blog mydevtricks.com.

💖 💪 🙅 🚩
jdoubek
Jan Doubek

Posted on October 28, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related