当前位置:  开发笔记 > 编程语言 > 正文

如何在c#中使用原始顺序对列表进行排名

如何解决《如何在c#中使用原始顺序对列表进行排名》经验,为你挑选了1个好方法。

我想从列表中进行排名并按原始顺序输出.

到目前为止这是我的代码:

     var data = new[] { 7.806468478, 7.806468478, 7.806468478, 7.173501754, 7.173501754, 7.173501754, 3.40877696, 3.40877696, 3.40877696, 
            4.097010736, 4.097010736, 4.097010736, 4.036494085, 4.036494085, 4.036494085, 38.94333318, 38.94333318, 38.94333318, 14.43588131, 14.43588131, 14.43588131 };


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

但是,结果将从降序开始:

排行

我想要的是按原始顺序显示.

例如:Rank = 3,Rank = 3,Rank = 3,Rank = 4,Rank = 4,Rank = 4等...

谢谢.



1> lc...:

使用你拥有的,一种方法是跟踪原始顺序并再次排序(丑陋且可能很慢):

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

我建议你建议用你的排名创建一个字典,并将其与你的列表一起加入:

var rankings = data.Distinct()
                   .OrderByDescending(x => x)
                   .Select((g, i) => new { Key = g, Rank = i + 1 })
                   .ToDictionary(x => x.Key, x => x.Rank);

var output = data.Select(x => new { Col1 = x, Rank = rankings[x] })
                 .ToList();

正如@AntonínLejsek所指出的那样,取代上述GroupBy呼叫Distinct()是要走的路.

注意doubles不是精确类型,因此实际上不是查找表中值的良好候选者,我也不建议使用GroupBy/ Distinct将浮点值作为键.请注意您的精确度并考虑使用适当的字符串转换.鉴于此,您可能希望定义一个epsilon值并GroupBy完全放弃LINQ ,而是选择将每个数据点封装到(非匿名)引用类型中,然后遍历排序列表并分配排名.例如(免责声明:未经测试):

class DataPoint
{
    decimal Value { get; set; }
    int Rank { get; set; }
}

var dataPointsPreservingOrder = data.Select(x => new DataPoint {Value = x}).ToList();

var sortedDescending = dataPointsPreservingOrder.OrderByDescending(x => x.Value).ToList();

var epsilon = 1E-15; //use a value that makes sense here

int rank = 0;
double? currentValue = null;

foreach(var x in sortedDescending)
{
    if(currentValue == null || Math.Abs(x.Value - currentValue.Value) > epsilon) 
    {
        currentValue = x.Value;
        ++rank;
    }
    x.Rank = rank;
}


`.ToString()`失去一些精度,因为默认情况下它只显示最多15-16个有效数字,所以我认为没有它会更好.第一个例子必须以类似`.OrderBy(x => x.Col1.Index)的方式结束.选择(x => new {Col1 = x.Col1.Item,x.Rank})`以便编译
推荐阅读
kikokikolove
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有