【问题标题】:League table sorting to get the player rank排行榜排序得到玩家排名
【发布时间】:2019-03-22 19:43:18
【问题描述】:

我正在尝试根据分数查找玩家的记录。如果两名球员得分相同,那么比赛次数少的球员排名靠前。如果两名球员的得分和比赛次数并列,那么在球员名单中排名第一的球员排名更高。

这是迄今为止我尝试过的代码。

http://sandbox.onlinephpfunctions.com/code/ca5f93990e1cb6a69bbbd734afde32f1ffa51522

但我得到的答案不正确。

   <?php
    class LeagueTable
    {
        public function __construct($players)
        {
            $this->standings = array();
            foreach($players as $index => $p)
            {
                $this->standings[$p] = array
                (
                    'index' => $index,
                    'games_played' => 0, 
                    'score' => 0
                );
            }
        }

    public function recordResult($player, $score)
    {
        $this->standings[$player]['games_played']++;
        $this->standings[$player]['score'] += $score;
    }

    public function playerRank($rank)
    {
        $ranks = $this->standings;
        uasort($ranks, function ($a, $b) {
            if ($a['score'] >= $b['score']) {
                if ($a['score'] == $b['score']) {
                    if ($a['games_played'] >= $b['games_played']) {
                        if ($a['games_played'] == $b['games_played']) {
                            return $a['index'] > $b['index'];
                        } else {
                            return true;
                        }
                    } else {
                        return false;
                    }
                } else {
                    return true;
                }
            } else {
                return false;
            }
        });

        print_r($this->standings);
    }
}

$table = new LeagueTable(array('Mike', 'Chris', 'Arnold'));
$table->recordResult('Mike', 2);
$table->recordResult('Mike', 3);
$table->recordResult('Arnold', 5);
$table->recordResult('Chris', 5);
echo $table->playerRank(1);

结果

  I am getting Array 
    ( 
        [Mike] => Array 
            ( 
                [index] => 0 
                [games_played] => 2 
                [score] => 5 
            ) 

        [Chris] => Array 
            ( 
                [index] => 1 
                [games_played] => 1 
                [score] => 5 
            ) 

        [Arnold] => Array 
            ( 
                [index] => 2 
                [games_played] => 1 
                [score] => 5 
            ) 

    )  BUT my test says Example case: Wrong answer 
      Players have different scores: Wrong answer 
      Players tied by score: Wrong answer 
      Players tied by games played: Wrong answer 

【问题讨论】:

  • 你得到什么答案?请注明。
  • @Wreigh 我已经更新了问题

标签: php


【解决方案1】:

这个函数会做你想做的事。棘手的部分是您希望玩家拥有最高 分或最低 场数或最低 指数。因此,games_playedindex 的排序中每个测试的条件与score 的条件不同。排序后,我们返回与$rank 变量关联的键,记住排名从 1 开始,但键数组从 0 开始,所以我们必须从 $rank 中减去 1。

public function playerRank($rank)
{
    $ranks = $this->standings;
    uasort($ranks, function ($a, $b) {
        // sort by score
        if ($a['score'] != $b['score']) 
            return ($a['score'] > $b['score']) ? -1 : 1;
        // equal! sort by games played
        if ($a['games_played'] != $b['games_played'])
            return ($a['games_played'] < $b['games_played']) ? -1 : 1;
        // equal! sort by index
        return ($a['index'] < $b['index']) ? -1 : 1;
    });

    return array_keys($ranks)[$rank-1];
}

我在https://www.testdome.com/questions/php/league-table/15401?visibility=1 测试了这段代码,它通过了所有测试。

【讨论】:

    【解决方案2】:

    uasort 需要返回 0、-1 或 1。我也重新排列了一点。您还需要使用$rank发送的播放器和结束。

    public function playerRank($rank) {
        // sort standings
        uasort($this->standings, function ($a, $b) {
            if($a['score'] == $b['score']) {
                if($a['games_played'] == $b['games_played']) {
                    if($a['index'] == $b['index']) {
                        return 0;
                    }
                    return $a['index'] < $b['index'] ? -1 : 1;
                }
                return $a['games_played'] < $b['games_played'] ? -1 : 1;
            }
            return $a['score'] < $b['score'] ? -1 : 1;
        });
        // return player at rank
        return print_r($this->standing[$rank], 1);
    }
    

    【讨论】:

    【解决方案3】:

    使用php函数数组multisort()

    http://www.php.net/array_multisort

    <?php
        class LeagueTable
        {
            public function __construct($players)
            {
                $this->standings = array();
                foreach($players as $index => $p)
                {
                    $this->standings[$p] = array
                    (
                        'index' => $index,
                        'games_played' => 0, 
                        'score' => 0
                    );
                }
            }
    
        public function recordResult($player, $score)
        {
            $this->standings[$player]['games_played']++;
            $this->standings[$player]['score'] += $score;
        }
    
    
        public function playerRank()
        {
            $data = $this->standings;
    
    
            array_multisort(array_column($data, 'score'),  SORT_DESC,
                    array_column($data, 'games_played'), SORT_ASC,
                    array_column($data, 'index'), SORT_ASC,
                    $data);
    
            print_r($data);
        }
    }
    
    $table = new LeagueTable(array('Mike', 'Chris', 'Arnold'));
    $table->recordResult('Mike', 2);
    $table->recordResult('Mike', 3);
    $table->recordResult('Arnold', 5);
    $table->recordResult('Chris', 5);
    echo $table->playerRank();
    

    【讨论】:

    • 我发现 multisort 更简洁一些。
    • cecil:我完全同意 :)
    • @cecilmerrelakabringrainfire 这很简单(而且简单)但是手册中的这一行让我担心它是否总是能正确解决得分和比赛的情况相同:“如果两个成员比较相等,则它们在排序数组中的相对顺序未定义”
    • @Nick 在两个相等的情况下,会回退到按数组中的索引号排序。
    • @cecilmerrelakabringrainfire 应该这样做,尽管您想对索引 ASC 进行排序,以便它与 games_played 的排序方向相同(越低越好)。你应该更新你的答案。
    【解决方案4】:

    使用 array_multisort() 函数我稍微改进了答案,并且 我已经在 https://www.testdome.com/questions/php/league-table/15401?visibility=1 它通过了所有测试。

       public function playerRank(int $rank) : string
        {
    
            $data = $this->standings;
            $sorted_data=[];
    
            array_multisort(
                    array_column($data, 'score'),  SORT_DESC,
                    array_column($data, 'games_played'), SORT_ASC,
                    array_column($data, 'index'), SORT_ASC,
                    $data);
    
             $current_rank = 1;
             foreach($data as $player_name => $value)
             {
                $sorted_data['rank'] = $current_rank;
                $sorted_data[$current_rank]['name'] = $player_name;
                $current_rank++;
             }
    
        return $sorted_data[strval($rank)]["name"];
        }
    

    【讨论】:

      猜你喜欢
      • 2020-06-15
      • 1970-01-01
      • 1970-01-01
      • 2015-05-04
      • 2014-05-24
      • 2015-01-29
      • 2015-03-01
      • 1970-01-01
      • 2018-01-31
      相关资源
      最近更新 更多