Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从球员各位置的得分列表中查找可能的最大总得分_C#_Linq - Fatal编程技术网

C# 从球员各位置的得分列表中查找可能的最大总得分

C# 从球员各位置的得分列表中查找可能的最大总得分,c#,linq,C#,Linq,如果有一份球员名单,我如何找到球队的最高得分 我维护一个社交幻想联盟(澳大利亚规则)网站,在那里你可以在赛季开始时挑选18名球员,然后每周你选择一支由6名球员组成的球队,每个位置分配一名球员。您本周的得分是您选择的每个球员得分的总和。例如,如果每个球员得分50分,你的球队本周得分将为300分 为了在回合结束后分析您的团队,我想展示几个指标。第一个是每个位置的最高得分,第二个是本周的团队 我可以通过这样的操作计算出每个位置的最高分数(“球员分数列表”屏幕截图中的绿色突出显示) 然而,要计算出球队可

如果有一份球员名单,我如何找到球队的最高得分

我维护一个社交幻想联盟(澳大利亚规则)网站,在那里你可以在赛季开始时挑选18名球员,然后每周你选择一支由6名球员组成的球队,每个位置分配一名球员。您本周的得分是您选择的每个球员得分的总和。例如,如果每个球员得分50分,你的球队本周得分将为300分

为了在回合结束后分析您的团队,我想展示几个指标。第一个是每个位置的最高得分,第二个是本周的团队

我可以通过这样的操作计算出每个位置的最高分数(“球员分数列表”屏幕截图中的绿色突出显示)

然而,要计算出球队可能取得的最大得分比我想象的要困难得多。在这种情况下,各职位之间可能会分享高分。此外,你可能选择的“最好的球队”可能并不意味着该球员在某个位置的得分最高

在这个例子中,我计算出的该队的最佳得分(即每个位置上你可以挑选的最佳6名球员)是288。也就是说,将我在红色方框中突出显示的6个分数相加,得出288分。看看即使乔希·肯尼迪在“关”的位置上得了57分,你还是选择他在“FW”的位置更好,因为下一个最好的“FW”球员得分19分(托比·格林的)是23分请记住,在回合开始之前,您必须将一名球员分配到一个位置,这样您只能使用每个球员的一个分数。

有什么建议吗?我如何编写一个循环/查询,以提取球员列表和他们的得分,从而构成尽可能最好的团队得分288

为了获得更多信息,playerList是这样构建的,稍后我会在一些web服务调用之后添加实际分数,这些调用会获得统计数据(踢、手球等)

List playerList=new List();
foreach(团队中的var t)
{
playerList.AddRange(t.TeamSelections.Where(x=>x.DateInactive==null).OrderBy(x=>x.PlayerName).Select(p=>newplayerscore
{
TeamId=p.TeamId,
PlayerName=p.PlayerName,
俱乐部,
ClubAbbreviation=Helper.Stats.GetClubAbbreviation(p.Club),
TeamLeagueId=p.Team.LeagueId,
TeamSelection=p.TeamSelectionId
}));
}

我不知道如何挑选团队的规则,但大概六个角色中每一个都必须有一个玩家

如果你没有太多的玩家(例如,在上面的表格中,它可能会很有效),那么蛮力方法可能会奏效 然后,如果你有
n个
玩家,第一个玩家有
n个
选择,第二个玩家有
n-1个
(因为你不能让同一个玩家在两个不同的位置),等等。这就提供了总共
nP6
()的可能性。这是相当大的,数量级为
n⁶。
如果你想实现这一点,你可以快速而肮脏地实现一个六个深度的循环(确保排除已经选择的玩家),检查分数,并跟踪最高的一个(s)

减少检查可能性的一种方法,我认为这是合理的,就是:只从该位置前6名得分手中选择你在X位置的球员。直觉是这样的:如果我为我的其他位置选择了(最佳或不最佳)5名球员,我不可能为位置X选择所有6名最佳得分手!因此,至少有一个仍然可用。那我就只能从剩下的最好的中挑一个了。所以我当然可以排除那些没有进入前6名的人。当存在联系时,可能会出现问题,在这种情况下,出于安全考虑,任何与前6名中的任何一个职位有联系的人都可以留任

这样(假设没有关系),您只需搜索
6即可⁶可能性,最多(如果同一玩家在不同类别中获得前6名,则可能性较小)。而且,即使是对于一个大的列表,最初对前6名的搜索也很容易处理


所有这些都可以用LINQ来完成,但不需要这样做。

所以这里就是它的结局。。可能有助于任何人在一组数字中选择尽可能高的总数。到目前为止,我还没有看到一个实例不能返回正确的结果。。请随意建议代码清理/优化

    private static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
    {
        return length == 1 ? list.Select(t => new[] {t}) : GetPermutations(list, length - 1).SelectMany(t => list.Where(o => !t.Contains(o)), (t1, t2) => t1.Concat(new[] {t2}));
    }

    public static List<PlayerScore> TeamOfTheWeek(List<PlayerScore> playerList)
    {
        // Remove the players who scored 0 accross the board.
        playerList.RemoveAll(player => player.Forward + player.TallForward + player.Offensive + player.Defensive + player.OnBaller + player.Ruck == 0);

        // Rank each player score within a position.
        var forwardRank = playerList.RankByDescending(p => p.Forward, (p, r) => new {Rank = r, Player = p});
        var tallForwardRank = playerList.RankByDescending(p => p.TallForward, (p, r) => new {Rank = r, Player = p});
        var offensiveRank = playerList.RankByDescending(p => p.Offensive, (p, r) => new { Rank = r, Player = p });
        var defensiveRank = playerList.RankByDescending(p => p.Defensive, (p, r) => new { Rank = r, Player = p });
        var onBallerRank = playerList.RankByDescending(p => p.Defensive, (p, r) => new { Rank = r, Player = p });
        var ruckRank = playerList.RankByDescending(p => p.Ruck, (p, r) => new { Rank = r, Player = p });

        for (int i = playerList.Count - 1; i >= 0; i--)
        {
            //var rankName = forwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Player.PlayerName;
            var fw = forwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var tf = tallForwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var off = offensiveRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var def = defensiveRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var ob = onBallerRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var ruck = ruckRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;

            if (fw >= 6 && tf >= 6 && off >= 6 && def >= 6 && ob >= 6 && ruck >= 6)
            {
                // Player is outside top 6 for each position so remove, and reduce permutations.
                playerList.RemoveAt(i);
            }
        }   

        // Now update the playerId as this is used to join back to the array later.
        var playerId = 0;
        foreach (var p in playerList.OrderBy(p => p.PlayerName))
        {
            p.Id = playerId;
            playerId = playerId + 1;
        }

        // Create and fill the position scores.
        List<int[]> positionScoreArray = new List<int[]>();
        foreach (var player in playerList.OrderBy(p => p.PlayerName))
        {
            // Player scored more than 0 so add to the positionScoreArray.
            int[] playerScores = { player.Forward, player.TallForward, player.Offensive, player.Defensive, player.OnBaller, player.Ruck };
            positionScoreArray.Add(playerScores);
        }

        // Players remaining in list pulled into array, ready for processing.
        string[] playerNameArray = playerList.OrderBy(x => x.PlayerName).Select(p => p.PlayerName).ToArray();

        // Load up the actual position scores to use in Parallel.For processing.
        for (int i = 0; i < playerNameArray.Length; i++)
        {
            for (int j = 0; j < positionScoreArray.Count; j++)
            {   
                if (j == 0)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.Forward;
                }
                if (j == 1)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.TallForward;
                }
                if (j == 2)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.Offensive;
                }
                if (j == 3)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.Defensive;
                }
                if (j == 4)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.OnBaller;
                }
                if (j == 5)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.Ruck;
                }
            }
        }

        Stopwatch parallelForEachStopWatch = new Stopwatch();
        parallelForEachStopWatch.Start();

        var count = 0;
        var playerIds = Enumerable.Range(0, playerNameArray.Length).ToList();
        var best = new { PlayerIds = new List<int>(), TeamScore = 0 };
        var positions = new[] { "FW", "TF", "Off", "Def", "OB", "Ruck" };

        // Thread safe the Parallel.ForEach
        lock (ThreadSafeObject)
        {
            Parallel.ForEach(GetPermutations(playerIds, positions.Length), perm =>
                {
                    var teamScore = 0;
                    var players = perm.ToList();
                    for (int i = 0; i < positions.Length; i++) teamScore += positionScoreArray[players[i]][i];
                    if (teamScore > best.TeamScore) best = new {PlayerIds = players, TeamScore = teamScore};
                    if (count++%100000 == 0) Debug.WriteLine($"{count - 1:n0}");
                }
            );
        }

        parallelForEachStopWatch.Stop();
        TimeSpan parallelForEach = parallelForEachStopWatch.Elapsed;

        Debug.WriteLine($"Parallel.ForEach (secs): {parallelForEach.Seconds}");
        Debug.WriteLine($"Permutations: {count:n0}");
        Debug.WriteLine($"Team Score: {best.TeamScore}");

        // Track Parallel.ForEach result.
        var tcTotwRequest = new TelemetryClient();
        tcTotwRequest.TrackEvent($"Permutations: {count:n0} Score: {best.TeamScore} Time (sec): {parallelForEach.Seconds}");

        lock (ThreadSafeObject)
        {
            if (best.PlayerIds.Count > 0)
            {
                for (int i = 0; i < positions.Length; i++)
                {
                    // Update the playerList, marking best players with TeamOfTheWeek position.
                    var player = playerList.FirstOrDefault(p => p.Id == best.PlayerIds[i]);
                    if (player != null)
                    {
                        player.TeamOfTheWeekPosition = positions[i];
                        player.TeamOfTheWeekScore = best.TeamScore;
                    }
                }
            }
        }

        return playerList.OrderBy(p => p.PlayerName).ToList();
    }
}
私有静态IEnumerable GetPermutations(IEnumerable列表,int-length)
{
返回长度==1?list.Select(t=>new[]{t}):GetPermutations(list,length-1)。SelectMany(t=>list.Where(o=>!t.Contains(o)),(t1,t2)=>t1.Concat(new[]{t2});
}
每周的公共静态列表(列表播放列表)
{
//移除棋盘上得分为0的玩家。
playerList.RemoveAll(player=>player.Forward+player.TallForward+player.进攻+player.防守+player.OnBaller+player.Ruck==0);
//在一个位置内对每个球员的得分进行排名。
var forwardRank=playerList.RankByDescending(p=>p.Forward,(p,r)=>new{Rank=r,Player=p});
var tallForwardRank=playerList.RankByDescending(p=>p.TallForward,(p,r)=>new{Rank=r,Player=p});
var offensiveRank=玩家列表。Rankbydesking(p=>p.进攻,(p,r)=>new{Rank=r,Player=p});
var defensiveRank=球员名单。RankByDescending(p=>p.防守,(p,r)=>new{Rank=r,Player=p});
var onBallerRank=球员名单。RankByDescending(p=>p.防守,(p,r)=>new{Rank=r,Player=p});
var ruckRank=playerList.RankByDescending(p=>p.Ruck,(p,r)=>new{Rank=r,Player=p});
对于(int i=playerList.Count-1;i>=0;i--)
{
List<PlayerScore> playerList = new List<PlayerScore>();

foreach (var t in teams)
{
    playerList.AddRange(t.TeamSelections.Where(x => x.DateInactive == null).OrderBy(x => x.PlayerName).Select(p => new PlayerScore
    {
        TeamId = p.TeamID,
        PlayerName = p.PlayerName,
        Club = p.Club,
        ClubAbbreviation = Helper.Stats.GetClubAbbreviation(p.Club),
        TeamLeagueId = p.Team.LeagueId,
        TeamSelection = p.TeamSelectionId
    }));
}
    private static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
    {
        return length == 1 ? list.Select(t => new[] {t}) : GetPermutations(list, length - 1).SelectMany(t => list.Where(o => !t.Contains(o)), (t1, t2) => t1.Concat(new[] {t2}));
    }

    public static List<PlayerScore> TeamOfTheWeek(List<PlayerScore> playerList)
    {
        // Remove the players who scored 0 accross the board.
        playerList.RemoveAll(player => player.Forward + player.TallForward + player.Offensive + player.Defensive + player.OnBaller + player.Ruck == 0);

        // Rank each player score within a position.
        var forwardRank = playerList.RankByDescending(p => p.Forward, (p, r) => new {Rank = r, Player = p});
        var tallForwardRank = playerList.RankByDescending(p => p.TallForward, (p, r) => new {Rank = r, Player = p});
        var offensiveRank = playerList.RankByDescending(p => p.Offensive, (p, r) => new { Rank = r, Player = p });
        var defensiveRank = playerList.RankByDescending(p => p.Defensive, (p, r) => new { Rank = r, Player = p });
        var onBallerRank = playerList.RankByDescending(p => p.Defensive, (p, r) => new { Rank = r, Player = p });
        var ruckRank = playerList.RankByDescending(p => p.Ruck, (p, r) => new { Rank = r, Player = p });

        for (int i = playerList.Count - 1; i >= 0; i--)
        {
            //var rankName = forwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Player.PlayerName;
            var fw = forwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var tf = tallForwardRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var off = offensiveRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var def = defensiveRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var ob = onBallerRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;
            var ruck = ruckRank.First(x => x.Player.PlayerName == playerList[i].PlayerName).Rank;

            if (fw >= 6 && tf >= 6 && off >= 6 && def >= 6 && ob >= 6 && ruck >= 6)
            {
                // Player is outside top 6 for each position so remove, and reduce permutations.
                playerList.RemoveAt(i);
            }
        }   

        // Now update the playerId as this is used to join back to the array later.
        var playerId = 0;
        foreach (var p in playerList.OrderBy(p => p.PlayerName))
        {
            p.Id = playerId;
            playerId = playerId + 1;
        }

        // Create and fill the position scores.
        List<int[]> positionScoreArray = new List<int[]>();
        foreach (var player in playerList.OrderBy(p => p.PlayerName))
        {
            // Player scored more than 0 so add to the positionScoreArray.
            int[] playerScores = { player.Forward, player.TallForward, player.Offensive, player.Defensive, player.OnBaller, player.Ruck };
            positionScoreArray.Add(playerScores);
        }

        // Players remaining in list pulled into array, ready for processing.
        string[] playerNameArray = playerList.OrderBy(x => x.PlayerName).Select(p => p.PlayerName).ToArray();

        // Load up the actual position scores to use in Parallel.For processing.
        for (int i = 0; i < playerNameArray.Length; i++)
        {
            for (int j = 0; j < positionScoreArray.Count; j++)
            {   
                if (j == 0)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.Forward;
                }
                if (j == 1)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.TallForward;
                }
                if (j == 2)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.Offensive;
                }
                if (j == 3)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.Defensive;
                }
                if (j == 4)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.OnBaller;
                }
                if (j == 5)
                {
                    var player = playerList.FirstOrDefault(p => p.PlayerName == playerNameArray[i]);
                    if (player != null)
                        positionScoreArray[i][j] = player.Ruck;
                }
            }
        }

        Stopwatch parallelForEachStopWatch = new Stopwatch();
        parallelForEachStopWatch.Start();

        var count = 0;
        var playerIds = Enumerable.Range(0, playerNameArray.Length).ToList();
        var best = new { PlayerIds = new List<int>(), TeamScore = 0 };
        var positions = new[] { "FW", "TF", "Off", "Def", "OB", "Ruck" };

        // Thread safe the Parallel.ForEach
        lock (ThreadSafeObject)
        {
            Parallel.ForEach(GetPermutations(playerIds, positions.Length), perm =>
                {
                    var teamScore = 0;
                    var players = perm.ToList();
                    for (int i = 0; i < positions.Length; i++) teamScore += positionScoreArray[players[i]][i];
                    if (teamScore > best.TeamScore) best = new {PlayerIds = players, TeamScore = teamScore};
                    if (count++%100000 == 0) Debug.WriteLine($"{count - 1:n0}");
                }
            );
        }

        parallelForEachStopWatch.Stop();
        TimeSpan parallelForEach = parallelForEachStopWatch.Elapsed;

        Debug.WriteLine($"Parallel.ForEach (secs): {parallelForEach.Seconds}");
        Debug.WriteLine($"Permutations: {count:n0}");
        Debug.WriteLine($"Team Score: {best.TeamScore}");

        // Track Parallel.ForEach result.
        var tcTotwRequest = new TelemetryClient();
        tcTotwRequest.TrackEvent($"Permutations: {count:n0} Score: {best.TeamScore} Time (sec): {parallelForEach.Seconds}");

        lock (ThreadSafeObject)
        {
            if (best.PlayerIds.Count > 0)
            {
                for (int i = 0; i < positions.Length; i++)
                {
                    // Update the playerList, marking best players with TeamOfTheWeek position.
                    var player = playerList.FirstOrDefault(p => p.Id == best.PlayerIds[i]);
                    if (player != null)
                    {
                        player.TeamOfTheWeekPosition = positions[i];
                        player.TeamOfTheWeekScore = best.TeamScore;
                    }
                }
            }
        }

        return playerList.OrderBy(p => p.PlayerName).ToList();
    }
}