如何在 C# 中对元素进行排名,尤其是当它有重复项时

How to rank elements in c# especially when it has duplicates

我有一个对数组元素进行排名的需求,并且数组有重复值。我尝试遵循此 Ranking items in a list with LINQ 但是当数组中有重复值时这不起作用。在 c# 中有什么简单的方法可以做到这一点?

例如:

input = [650,150,150,200] 
output = [1,3,3,2]

例如:

input = [650,200,200,150] 
output = [1,2,2,3]

更新:需求如下,如果我在数组中再增加一个元素呢 例如:[650,150,150,200,100] 输出需要是 [1,3,3,2,5] 而不是 [1,3,3,2,4]

您可以创建一个不同且有序的项目数组,然后使用索引确定每个项目的排名。

var ranks = input.Distinct().OrderByDescending(x => x).ToArray();
var ranked = input.Select(x => Array.IndexOf(ranks, x) + 1);

Working example


评论后更新

如果需要跳过排名,只需删除 Distinct:

var ranks = input.OrderByDescending(x => x).ToArray();
var ranked = input.Select(x => Array.IndexOf(ranks, x) + 1);

Array.IndexOf有重复时取第一个元素

Working example

您可以创建字典作为排名查找源:

int[] array = new[] {650,150,150,200};
Dictionary<int, int> numRanks = array
    .GroupBy(i => i)
    .OrderByDescending(g => g.Key)
    .Select((g, index) => (num:g.Key, rank:index+1))
    .ToDictionary(x => x.num, x => x.rank);
int[] result = array.Select(i => numRanks[i]).ToArray();

对于更新后的要求,您可以使用类似的方法 Lookup<TKey, TValue>:

var rankLookup = array
    .OrderByDescending(i => i)
    .Select((num, index) => (num, index))
    .ToLookup(x => x.num, x => x.index + 1);
int[] result = array.Select(i => rankLookup[i].First()).ToArray();

查找就像一本允许重复键的字典。你需要在这里使用 First 因为你只对排名感兴趣。如果你使用 Count() 你就会知道它有多少重复项。