首页 > 解决方案 > 使用 LINQ 查询或类似方法优化运动员比赛列表

问题描述

我正在尝试构建一个函数来优化运动员在比赛中的比赛结果。假设我有一类运动员:

public class Athlete
{
    public int ID {get; set; }
    public string Name { get; set; }
    public int RunningAbility { get; set; }
    public int SwimmingAbility { get; set; }

    public readonly List<Attempt> { get; set; }
}

每位运动员在比赛中进行 2 次尝试。他们可以参加两次游泳比赛,两次跑步比赛,也可以各做一次。唯一的规定是跑步者和游泳者的人数必须相等;因此,如果有 3 名运动员,则需要进行 6 次尝试——3 次跑步和 3 次游泳。

Attempt 类如下所示:

public class Attempt
{
    public string AthleteID { get; set; }
    public string EventName { get; set; }
}

我一直在试图弄清楚如何制作一个具有最佳方案的尝试列表。

public void Main(){
    var people = new List<Athlete>() {
        new Athlete()
        {
            Name = "Bob",
            RunningAbility = 10,
            SwimmingAbility = 10
        },
        new Athlete()
        {
            Name = "Joe",
            RunningAbility = 8,
            SwimmingAbility = 2
        },
        new Athlete()
        {
            Name = "Sue",
            RunningAbility = 3,
            SwimmingAbility = 7
        },
    };

    var attempts = GetBestPossible(people);
}

private List<Attempt> GetBestPossible(List<People> people)
{
    var attempts = new List<Attempt>();
    //Each Person must compete twice and can either use both attempts in same event or one in each event
    //The entire team Must have equal attempts for running and swimming - i.e. 3 attempt swimming and 3 attempts running in this case.
    //How would I make a linq query or comparable solution on people that would give me a 
    //list of attempts with the max ability utilized for both events?
    //Expected outcome for attempts list would be 
    //Name  Event
    //Bob   Running
    //Bob   Swimming
    //Joe   Running
    //Joe   Running
    //Sue   Swimming
    //Sue   Swimming

    //Meets criteria of having each Person attempt twice 
    //and equal attempts in both events with MAX ability

    return attempts;
}

有谁知道是否有办法用 Linq 做到这一点,或者如果给定的细节不可能做到这一点?我不知道从哪里开始,所以非常感谢任何帮助!

编辑:List<Attempt>向我的班级添加了一个属性Person,我仍然不确定如何解决我的问题,但我想我需要编写一个函数,循环遍历每个运动员实例的所有可能结果,然后计算并以某种方式确定哪个结果是最适合这两个事件。

标签: c#linq

解决方案


这里有一些希望能以某种方式帮助解决问题的方法。

您有两个游戏/比赛,让我们为它们创建一个enum

//...
public enum Competitions { Running, Swimming }
//...

Attempt,最大。Athlete无论比赛类型如何,每个对象都有两个实例。

//...
public class Attempt
{
    public Competitions Competition { get; set; } 
    public int Score { get; set; }
}
//...

Athlete班级:

//...
public class Athlete
{       
    public string Name { get; set; }

    public readonly List<Attempt> Attempts = new List<Attempt>();

    public override string ToString() => Name;
}
//...

还有一个类,将是每个运动员的报告/统计/状态(您可以命名)条目。

//...
public class Statistics
{
    public string Name { get; set; }
    public int Running { get; set; }
    public int Swimming { get; set; }
    public int TotalScore { get => Running + Swimming; }
    public int RunningRank { get; set; }
    public int SwimmingRank { get; set; }
    public int GeneralRank { get; set; }
}
//...

在您的实现中,您List<Athlete>填写了一些条目,例如:

//...
List<Athlete> Athletes = new List<Athlete>();

private void CreateList()
{
    Athletes.Clear();

    var jim = new Athlete { Name = "Jim" };
    jim.Attempts.Add(new Attempt { Competition = Competitions.Swimming, Score = 1 });
    jim.Attempts.Add(new Attempt { Competition = Competitions.Swimming, Score = 2 });

    var joe = new Athlete { Name = "Joe" };
    joe.Attempts.Add(new Attempt { Competition = Competitions.Running, Score = 7 });
    joe.Attempts.Add(new Attempt { Competition = Competitions.Swimming, Score = 2 });

    var sue = new Athlete { Name = "Sue" };
    sue.Attempts.Add(new Attempt { Competition = Competitions.Running, Score = 3 });
    sue.Attempts.Add(new Attempt { Competition = Competitions.Swimming, Score = 7 });

    var bob = new Athlete { Name = "Bob" };
    bob.Attempts.Add(new Attempt { Competition = Competitions.Running, Score = 10 });
    bob.Attempts.Add(new Attempt { Competition = Competitions.Swimming, Score = 10 });

    var ben = new Athlete { Name = "Ben" };
    ben.Attempts.Add(new Attempt { Competition = Competitions.Running, Score = 5 });

    var sam = new Athlete { Name = "Sam" };
    sam.Attempts.Add(new Attempt { Competition = Competitions.Running, Score = 6 });
    sam.Attempts.Add(new Attempt { Competition = Competitions.Running, Score = 4 });

    Athletes.AddRange(new[] { jim, joe, sue, bob, ben, sam });
}
//...

现在让我们为每个成员创建一个统计数据或报告,其中他们的跑步和游泳尝试的总和相等。

//...
private IEnumerable<Statistics> CreateStatistics()
{
    var ath = Athletes.Where(x => x.Attempts.Count() == 2
    && x.Attempts.First().Competition != x.Attempts.Last().Competition);

    var abi = (from a in ath
                select new Statistics
                {
                    Name = a.Name,
                    Running = a.Attempts
                    .First(r => r.Competition == Competitions.Running).Score,
                    Swimming = a.Attempts
                    .First(s => s.Competition == Competitions.Swimming).Score,
                }).ToList();

    foreach (var a in abi)
    {
        a.RunningRank = 1 + abi.Select(r => r.Running).OrderByDescending(r => r)
            .ToList().IndexOf(a.Running);

        a.SwimmingRank = 1 + abi.Select(s => s.Swimming).OrderByDescending(s => s)
            .ToList().IndexOf(a.Swimming);

        a.GeneralRank = 1 + abi.Select(t => t.TotalScore).OrderByDescending(t => t)
            .ToList().IndexOf(a.TotalScore);
    }

    return abi;
}
//...

结果是:

SOQ60819266

如您所见,查询仅从列表中选择了三个成员,并为每个成员创建了一个统计条目,显示他们的得分并计算他们在每场比赛中的排名,以及总排名或总排名。

祝你好运。


推荐阅读