Question

In database(SQL Server), say, one column values are like:

Col1
====
10
5
15
20
5
10
2

This is like list of integer data.

Rank should be:

Col1 Rank
==== ====
20    1
15    2
10    3
10    3
5     4
5     4
2     5

I have tried in following manner:

1) First sort the list of data in descending order of "Col1" value
2) Find the index of a particular record using FindIndex() method.
3) Then Rank = Index + 1

But it will only work if the data are unique. It fails when same "Col1" values are present in multiple rows as the index is returning 0, 1, 2, 3, 4, 5, 6.

How to calculate the rank when the list contains data which are not distinct(in most cases!) using C# LINQ?

Was it helpful?

Solution

Why not do it in the database?

SELECT [Col1], DENSE_RANK() OVER (ORDER BY Col1 DESC) AS [Rank]
FROM Table

But if you must do it in C#

var data = new List<int>();
var rankings = data.OrderByDescending(x => x)
                   .GroupBy(x => x)
                   .SelectMany((g, i) =>
                       g.Select(e => new { Col1 = e, Rank = i + 1 }))
                   .ToList();

OTHER TIPS

If you would do it in the database (either by running a query or by selecting from a VIEW), the query/view should be thus:

SELECT [Col1], DENSE_RANK() OVER (ORDER BY Col1 DESC) AS [Rank]
FROM OriginalTable

This is much easier and faster than doing it in C# or any other language that must first retrieve the data and then post-process it.

In C#:

var data = new List<int> { 10, 12, 7, 8, 7, 6, 3, 3, 4 };
var rankings = data.OrderByDescending(x => x).GroupBy(x => x)
                   .SelectMany((g, i) =>
                       g.Select(e => new { Col1 = e, Rank = i + 1 }))
                   .ToList();
var persons = Predictions
    .OrderByDescending(s => s.Points)
    .GroupBy(g => .Points)
    .SelectMany((g, i) => g.Select(s => new{ Rank = i + 1,s.Player,s.Points}).ToList());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top