按大多数最低出现次数排序列表

时间:2016-10-18 06:59:24

标签: c# sorting

我已经玩了很长一段时间,但是无法弄清楚或找到关于它的现有问题。我正在为比赛得分编写一个C#工具,我需要做出总体结果。对于这个结果,一些特殊规则适用于我无法找到最佳方法:

我有一个包含比赛结果的列表(获胜者获得0分,第二名获得2分,第三名获得3等等)。为了使结果有效,我们首先按所有点的总和进行排序。当这样做时,仍有可能驱动程序共享相同数量的点数。在这种情况下,我们必须查看他们的最佳结果,例如:

车手1得分:0 + 0 + 4 = 4 司机2得分:2 + 2 + 0 = 4

在这种情况下,驾驶员1将首先是因为他获得了最多的胜利,因此他只有一次胜利。这适用于所有参与者。

更新 我看到的数据模型如下:

    public class SerieResultForPilot {
            public long Position { get; set; }
            public Pilot Pilot { get; set; }
            public List<SerieResultEntry> SerieResultEntries { get; set; }
            public long Total { get; set; }
        }

        public class SerieResultEntry {
            public long Points { get; set; }
            public long Penalties { get; set; }
        }

我目前订购的顺序但是工作方式不正确:

       var orderedList = serieResultList.OrderBy(rfp => rfp.Total);
            for (int i = 0; i < pilots.Count; i++) {
                orderedList = orderedList.ThenBy(c => c.SerieResultEntries.Count(sre => sre.Points == i));
            }

我希望有人可以帮我解决这个问题,因为我在这里找不到这样的问题。

提前致谢, 标记

解决方案 比较功能

    public class SerieResultForPilot {
            public long Position { get; set; }
            public Pilot Pilot { get; set; }
            public List<SerieResultEntry> SerieResultEntries { get; set; }
            public long Total { get; set; }

            public long CompareTo(SerieResultForPilot other) {
                var result = this.Total - other.Total;
                if (result != 0) {
                    return result;
                }
                var thisResults = this.SerieResultEntries.OrderBy(x => x.Points).Select(x => x.Points).ToArray();
                var otherResults = other.SerieResultEntries.OrderBy(x => x.Points).Select(x => x.Points).ToArray();
                for (var i = 0; i < thisResults.Length; i++) {
                    if (thisResults[i] != otherResults[i]) {
                        return thisResults[i] - otherResults[i];
                    }
                }
                return 0;
            }
        }

        public class SerieResultEntry {
            public long Points { get; set; }
            public long Penalties { get; set; }
        }

排序

    var orderedList = serieResultList.OrderBy(rfp => rfp.Total);
    foreach (var result in serieResultList) {
          orderedList = orderedList.ThenBy(c => c.CompareTo(result));
    }

4 个答案:

答案 0 :(得分:2)

你可以在类构建中围绕结果实现IComparable接口。

根据您的数据模型,计算方法可能看起来像那样

public int CompareTo(SerieResultForPilot other){
    var result this.Total - other.Total;
    if (result != 0){
        return result;
    }else{
        var thisResults = this.SerieResultEntries.OrderBy(x => x.SerieResultEntries.Points).toArray();
        var otherResults = his.SerieResultEntries.OrderBy(x => x.SerieResultEntries.Points).toArray();
        for (var i=0; i< thisResults.Count; i++){
            if (thisResults[i] != otherResults[i]){
                return thisResults[i] - otherResults[i];
            }
        }
        return 0;
    }
}

IComparable接口的文档https://msdn.microsoft.com/pl-pl/library/system.icomparable(v=vs.110).aspx

答案 1 :(得分:0)

也许不是效率最高的,但我认为这样做会很好:

drivers.OrderBy(x => new { x.Sum(y => y.Points), 
    x.Sum(y => y.Points.Where(t => t.Points = 4)), x.Sum(y => y.Points.Where(t => t.Points = 3)) });

假设点是为每个驱动程序存储的可枚举。

答案 2 :(得分:0)

查看您的代码,我认为您需要做的就是将ThenBy替换为ThenByDescending。 (你希望列表顶部大多数得分较低的驾驶员。)它还依赖于最大比赛得分低于驾驶员数量 - 也许你需要一个<=而不是<而不是for循环中的{{1}}?

这不是最有效的方式,但它非常聪明 - 我很难想出一些使用更少行代码的东西

答案 3 :(得分:0)

你需要先找不到。获胜者和每位车手的得分总和,然后根据他们的得分和胜利对记录进行排序,如下例所示:

public class LinqUtil<T> where T : BaseClass
{
    public static void MyScore()
    {
        List<DriverScore> scores = new List<DriverScore>
        {
            new DriverScore {driverId="driver2",score=2 },
            new DriverScore {driverId="driver2",score=2 },
            new DriverScore {driverId="driver2",score=0 },
            new DriverScore {driverId="driver1",score=0 },
            new DriverScore {driverId="driver1",score=0 },
            new DriverScore {driverId="driver1",score=4 },
        };

        var _score = (from s in scores
                    group s by s.driverId into g
                    select new
                    {
                        driverId = g.Key,
                        Win = g.Count(x => x.score == 0),
                        Score = g.Sum(x => x.score)
                    }).OrderByDescending(x=>x.Score).ThenByDescending(x=>x.Win);
        foreach(var _s in _score)
        {
            Console.WriteLine(_s.driverId + " " + _s.Win + " " + _s.Score);
        }


    }
}