【问题标题】:2 dimensional associative array sorting with conditional statements in PHP在 PHP 中使用条件语句进行二维关联数组排序
【发布时间】:2019-03-05 09:51:26
【问题描述】:

我无法弄清楚如何解决这个问题,它来自一个免费的在线测试网站。这是链接:https://www.testdome.com/questions/php/league-table/19939?questionIds=7278,19939&generatorId=30&type=fromtest&testDifficulty=Hard

但为了更清楚,我也在写这个问题和我的答案。开始的答案在上面写的链接中。

问题:

LeagueTable 类跟踪联盟中每个玩家的得分。每场比赛结束后,玩家使用 recordResult 函数记录他们的得分。

玩家在联赛中的排名使用以下逻辑计算:

得分最高的玩家排名第一(排名 1)。得分最低的玩家排名最后。 如果两名球员得分相同,则比赛次数最少的球员排名较高。 如果两名球员的得分和比赛次数并列,那么在球员名单中排名第一的球员排名更高。 实现 playerRank 函数,返回给定排名的玩家。

例如:

$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);

所有玩家的得分相同。不过,阿诺德和克里斯的比赛场次都比迈克少,而且由于克里斯在球员名单中排在阿诺德之前,所以他排名第一。因此,上面的代码应该显示“Chris”。

我的代码:

<?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)
    {
        // I'm not sure what to do in here, not even sure where to place the conditional statements
        // but here's me trying to figure it out which I'm 90% sure I'm doing it wrong, 
        // since I'm using too many foreach function and arrays. Most probably not even close
        // to the correct answer.

        $comparison = $result = $this->standings;
        $player_names = array();

        foreach($this->standings as $name => $records)
        {
            foreach($comparison as $name_compare => $records_compare)
            {     
                if($this->standings[$name]['score'] > $comparison[$name_compare]['score'])
                {
                    $result[$name]['index'] = $this->standings[$name]['index'];
                }
                else if($this->standings[$name]['score'] == $comparison[$name_compare]['score']
                      && $this->standings[$name]['games_played'] < $comparison[$name_compare]['games_played'])
                {
                    $result[$name]['index'] = $this->standings[$name]['index'];
                }
                else if($this->standings[$name]['score'] == $comparison[$name_compare]['score']
                        && $this->standings[$name]['games_played'] == $comparison[$name_compare]['games_played'])
                {
                    $result[$name]['index'] = $this->standings[$name]['index'];
                }

                // This is where I'm confused, although there are conditional statemens there
                // but the code inside each "if" and "else if" is the same.

            }
        }

        foreach($result as $name => $records)
        {
            array_push($player_names,$name);
        }

        return $player_names[$rank-1]; //This should return "Chris" based on the record result, but it's not
    }
}

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

谁能帮我解决这个问题?

【问题讨论】:

  • usort函数排序数组 - php.net/manual/en/function.usort.php
  • 谢谢,但我仍然不知道如何应用usort 函数来回答这个问题。如果您能在答案部分告诉我您的方式,我将不胜感激,以便我更好地理解并了解有关数组排序的更多信息

标签: php php-7 php-7.1


【解决方案1】:

在你的情况下使用 usort

usort($this->standings, function($a, $b) {
  // Compare scores
  $r = $b['score'] - $a['score'];
  // If two players are tied on score, 
  // then the player who has played the fewest games is ranked higher
  if(! $r) {
    $r = $a['games_played'] - $b['games_played'];
  }
  // If two players are tied on score and number of games played, 
  // then the player who was first in the list of players is ranked higher
  if(! $r) {
    $r = $a['index'] - $b['index'];
  }
  return $r;        
});

// You can watch result of sorting
print_r($this->standings);

【讨论】:

    【解决方案2】:

    您可以在下面找到完整的答案

    <?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,
                    'rank' => $index
                );
            }
        }
    
        public function recordResult($player, $score)
        {
            $this->standings[$player]['games_played']++;
            $this->standings[$player]['score'] += $score;
        }
    
        function swap(&$x,&$y) {
            $tmp=$x;
            $x=$y;
            $y=$tmp;
        }  
    
        public function reRank()
        {
           //ranking all according to score
            foreach($this->standings as $player => $records) {
    
              foreach($this->standings as $player1 => $records1) {
    
                if (($records['score'] > $records1['score']) && ($records['rank'] >= $records1['rank']))
                {
                    $this->swap($this->standings[$player]['rank'],$this->standings[$player1]['rank']);
                }
    
                // according to game played
                if (($records['score'] == $records1['score']) && ($records['games_played'] > $records1['games_played']))
                {
                    $this->swap($this->standings[$player]['rank'],$this->standings[$player1]['rank']);
                }
    
                // according to index
                if (($records['score'] == $records1['score']) && ($records['games_played'] == $records1['games_played'])&&
                ($records['index'] > $records1['index']))
                {
                    $this->swap($this->standings[$player]['rank'],$this->standings[$player1]['rank']);
                }
              }
           }
        }
    
        public function playerRank($rank)
        {
            $this->reRank();
            foreach($this->standings as $player => $records)
            {
                if ($records['rank']==$rank-1)
                return $player;
            }
        }
    }
    
    $table = new LeagueTable(array('Chris', 'Mike', 'Arnold'));
    $table->recordResult('Mike', 2);
    $table->recordResult('Mike', 3);
    $table->recordResult('Arnold', 5);
    $table->recordResult('Chris', 5);
    
    echo $table->playerRank(1);
    ?>
    

    【讨论】:

    • 这似乎无法正确排序项目。返回的第一个项目名称应为 Chris,但此函数生成“Mike”。
    【解决方案3】:

    请尝试以下代码。它会起作用的。

    <?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,
                    'name' => $p
                );
            }
        }
    
        public function recordResult($player, $score)
        {
            $this->standings[$player]['games_played']++;
            $this->standings[$player]['score'] += $score;
        }
    
        public function playerRank($rank)
        {
    
            $comparison = $result = $this->standings;
            $player_names = array();
           
           usort($this->standings, "comparatorFunc");
           
    
            foreach($this->standings as $name => $records)
            {
                array_push($player_names,$records['name']);
            }
            // echo "hello<br>";
            // print_r($player_names);
            return $player_names[$rank-1]; 
        }
    }
    
    
    function comparatorFunc($a, $b) {
        # Compare scores
        $r = $b['score'] - $a['score'];
        # If two players are tied on score, 
        # then the player who has played the fewest games is ranked higher
        if(! $r) {
            $r = $a['games_played'] - $b['games_played'];
        }
        # If two players are tied on score and number of games played, 
        # then the player who was first in the list of players is ranked higher
        if(! $r) {
            $r = $a['index'] - $b['index'];
        }
        return $r;        
    }
        
    $table = new LeagueTable(array('Mike', 'Chris', 'Arnold'));
    $table->recordResult('Mike', 2);
    $table->recordResult('Mike', 6);
    $table->recordResult('Arnold', 2);
    $table->recordResult('Arnold', 3);
    $table->recordResult('Chris', 5);
    echo $table->playerRank(1);
    

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案4】:
    <?php
    class LeagueTable
    {
      public function __construct(array $players)
      {
         $this->standings = [];
         foreach ($players as $index => $p) {
            $this->standings[$p] = [
                'index'        => $index,
                'games_played' => 0,
                'score'        => 0
            ];
          }
       }
    
        public function recordResult(string $player, int $score): void
        {
           $this->standings[$player]['games_played']++;
           $this->standings[$player]['score'] += $score;
        }
    
        public function playerRank(int $rank): string
        {
           $result = '';
          /**
           * sort array
           */
           uasort($this->standings, function ($player, $other_player) {
                $r = $other_player['score'] - $player['score'];
                if (!$r) {
                     $r = $player['games_played'] - 
                             $other_player['games_played'];
                }
                if (!$r) {
                    $r = $player['index'] - $other_player['index'];
                }
               return $r;
             });
             if ($rank > count($this->standings)) {
                  $rank = count($this->standings);
             }
             $index = 1;
             foreach ($this->standings as $player => $player_result) {
               if ($index == $rank) {
                   $result = $player;
                   break;
                } else {
                   $index++;
                   continue;
               }
             }
            return $result;
           }
     }
    
          $table = new LeagueTable(array('Mike', 'Chris', 'Arnold', 'Ali', 
                                  'Ahmad'));
         $table->recordResult('Mike', 2);
         $table->recordResult('Mike', 3);
         $table->recordResult('Arnold', 5);
         $table->recordResult('Chris', 5);
         $table->recordResult('Ali', 6);
         $table->recordResult('Ahmad', 3);
         $table->recordResult('Ahmad', 3);
         echo $table->playerRank(1);
    

    【讨论】:

    • 您好,如果您能帮助我们了解您的代码的作用以及它如何解决 OP 的问题,那就太好了!
    猜你喜欢
    • 1970-01-01
    • 2017-12-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    相关资源
    最近更新 更多