Tuesday, October 19, 2010

Returning the row index using LINQ

Imagine you have a contest and each entry has a some points that they were awarded. To show an ordered list of them is easy enough. Something like the following will return the names and the related points.

Entries
.Select(entry => new {
entry.Name,
entry.TotalPoints,
}
)
.OrderBy (o => o.TotalPoints)

Now what if you wanted to show the rank (1st, 2nd, 3rd, etc) for each entry. So basically now we have three columns in the results: Rank, Name, TotalPoints. How would we do this?

The answer is hidden in the LINQ to Objects specially overloaded Select method that is available only when you use the Lambda syntax where if you specify a second parameter it will put the row index in it. Here is that same query, but with the Rank column added.

Entries.ToList()
.Select((entry, index) => new {
entry.Name,
entry.TotalPoints,
Rank = index + 1
}
)
.OrderBy (o => o.TotalPoints)


Notice how we used the ToList() to convert the query to a List first. This is critical as you will get a runtime error otherwise.

FYI, the error is: Unsupported overload used for query operator 'Select'.

Also note, the name index is not important. It is the order in the Select method that is important. The index is zero based, and I wanted to show 1 based Rankings so I added one to the index to get the Rank.

No comments: