【问题标题】:how to get the rank list of multiple number in a list using C#? [closed]如何使用 C# 获取列表中多个数字的排名列表? [关闭]
【发布时间】:2016-08-18 12:38:08
【问题描述】:

我在 C# 中有以下列表:

List<double> arr = new List<double> { 5, 10, 7, 15, 9, 21, 1 };

我想将他们的排名存储在另一个列表中,例如List&lt;double&gt; rank。最后我想得到以下内容:

6 3 5 2 4 1 7

我该怎么做?

【问题讨论】:

  • 排名是什么意思?问题不清楚,并且没有显示以前的尝试......
  • 我猜排名越低数字越高?
  • @Matias Cicero:最大的数的排名为 1,第二大的排名为 2,以此类推。最低的项目排名 = n

标签: c# ranking


【解决方案1】:

如果all arr 中的项distinct,你可以创建一个dictionary

  List<double> arr = new List<double> { 5, 10, 7, 15, 9, 21, 1 };

  var ranks = arr
    .OrderByDescending(item => item)
    .Select((item, index) => new {
      item = item,
      rank = index + 1,
    })
    .ToDictionary(x => x.item, x => x.rank);

然后使用ranks 找出给定相应排名的项目:

    int rankOf5 = ranks[5]; // 6

测试

   string test = string.Join(" ", arr.Select(x => ranks[x]));

   // 6  3  5  2  4  1  7
   Console.Write(test);

编辑:使用循环测试:

   foreach (var item in arr)
     Console.Write(ranks[item]);

或者

   for (int i = 0; i < arr.Count; ++i)
      Console.Write(ranks[arr[i]]); 

编辑 2 如果arr 可以有重复,例如

// 21 appears 2 times
List<double> arr = new List<double> { 5, 10, 7, 15, 9, 21, 21, 1 };

您可能想要计算所谓的密集排名

var ranks = arr
  .GroupBy(item => item)
  .OrderByDescending(chunk => chunk.Key)
  .Select((chunk, index) => new {
     item = chunk.Key,
     rank = index + 1
   })
  .ToDictionary(x => x.item, x => x.rank);

   string test = string.Join(" ", arr.Select(x => ranks[x]));

   // 6 3 5 2 4 1 1 7
   Console.Write(test);

【讨论】:

  • 我创建了循环,但出现错误。什么是解决方案for (int i = 0; i &lt; arr.Count; i++ ) Console.WriteLine(ranks[i]);
  • @Sawa:不是ranks[i],而是ranks[arr[i]];查看我的编辑
  • 我将这个想法用于 FCTH 方法,但出现以下错误 An item with the same key has already been added 这个错误的解决方案是什么?
  • @Sawa:正如我所说的“..*all* arr 中的项目是distinct..”;如果你有 duplicates,你应该做的第一件事是在这种情况下给出 rankdefinition。有两种流行的可能性:[1, 1, 10] -&gt; rank(1, 1, 3)(请注意2 的漏洞)和[1, 1, 10] -&gt; rank(1, 1, 2)(所谓的密集等级)
  • 因为21重复List&lt;double&gt; arr = new List&lt;double&gt; { 5, 10, 7, 15, 9, 21, 21, 1 };下面的列表不起作用,有什么解决办法?
【解决方案2】:

可能最短的方法是在订购列表后使用IndexOf

List<double> arr = new List<double> { 5, 10, 7, 15, 9, 21, 1 };
var ranking = arr.OrderByDescending(item => item)
                 .Select(item => arr.IndexOf(item)+1)
                 .ToList();

//Output: 6, 2, 5, 2, 4, 1, 7

或者只是玩OrderBySelect

var ranking = arr.Select((item, index) => new { Item = item, Index = index })
                 .OrderByDescending(item => item.Item)
                 .Select((item, index) => new { Item = item.Item, OriginalIndex = item.Index, Rank = ++index })
                 .OrderBy(item => item.OriginalIndex)
                 .Select(item => item.Rank)
                 .ToList();

//Output: 6, 2, 5, 2, 4, 1, 7

【讨论】:

  • 这看起来有点矫枉过正XD
  • @Neil - 第二个?没错,哈哈,只是在玩:)
  • 我喜欢第一个。好答案
  • @Neil - 谢谢 :) 只是无聊所以想到了第二个 - 如何获得排名并仍然保持原始订单只通过选择和订购哈哈
【解决方案3】:
List<double> arr = new List<double> { 5, 10, 7, 15, 9, 21, 1 };

var rankDict = arr.Distinct().OrderByDescending(num=>num)
    .Select((number, index) => new {Number = number, Rank = index})
    .ToDictionary(m => m.Number, m => m.Rank);

var rankedArray = new List<double>();

foreach(var num in arr)
{
    rankedArray.Add(rankDict[num] + 1);
}

Console.WriteLine(string.Join("-", rankedArray));

小提琴 - https://dotnetfiddle.net/7C5o52

【讨论】:

  • 我将您的想法用于以下列表。但是,这是行不通的,因为21 重复了List&lt;double&gt; arr = new List&lt;double&gt; { 5, 10, 7, 15, 9, 21, 21, 1 };
  • @Sawa- 在添加到字典之前尝试使用 distinct。
猜你喜欢
  • 1970-01-01
  • 2016-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多