按出现次数最少的数字对列表排序
本文关键字:数字 列表 排序 | 更新日期: 2023-09-27 18:13:25
我一直在玩这个相当一段时间了,但不能弄清楚或找到一个关于它的现有问题。我正在编写一个c#工具的比赛得分,我需要使一个整体的结果。对于这个结果,一些特殊的规则适用,我不知道最好的方法:
我有一个比赛结果列表(获胜者获得0分,第二名获得2分,第三名获得3分等)。为了使结果成立,我们首先对所有点求和。当这样做的时候,仍然有可能车手分享相同数量的积分。在这种情况下,我们必须看看他们的最佳结果,例如:
车手1得分:0 + 0 + 4 = 4车手2得分:2 + 2 + 0 = 4
在这种情况下,车手1将是第一名,因为他赢了最多的比赛,车手2将紧随其后,因为他只赢了一次。这应该适用于所有参与者。
更新:我的数据模型如下所示:
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));
}
我希望任何人都能帮我解决这个问题,因为我还没有在这里找到这样的问题。
提前感谢,马克。
<解决方案/strong>比较函数
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));
}
您可以在类构建中实现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
也许不是最有效的,但我认为这样做可以:
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)) });
假设points是存储在每个车手的可枚举对象
查看您的代码,我认为您需要做的就是将ThenBy
替换为ThenByDescending
。(您希望大多数分数较低的驱动程序位于列表的顶部。)它还依赖于最大比赛分数小于车手数量-也许你需要一个<=
而不是<
在你的for
循环?
这不是最有效的方式,但它非常聪明——我很难想出使用更少代码行的方法。
您需要首先找到no。每个车手的胜利和分数的总和,然后根据他们的分数和胜利对记录进行排序,如下面的示例所示:
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);
}
}
}