【问题标题】:Sorting racers / players by places按地点对赛车手/玩家进行排序
【发布时间】:2016-10-23 23:04:11
【问题描述】:

我有一些赛车手的数据,格式如下:

大批( array(name => "第一个赛车手", places => [1,3,1,5,6,2,6,7,8]), 数组(名称 => “第二名赛车手”,位置 => [2,4,2,5,7]) ... )

建议对它们进行排序的最佳方法,以便第一批赛车手拥有更好的位置。例如,如果第一个赛车手至少有一个第一名而另一个没有,则第一个在列表中更高。如果他们都获得第一名,请比较第一名的数量。如果数字也相等,则比较第二个位置,依此类推。

我的解决方案(看起来不是很优雅。也许可以更简单地完成):

$赛车手=数组( array('name' => "第一个赛车手", 'places' => [1,3,1,5,6,2,6,7,8,9]), array('name' => "第二个赛车手", 'places' => [1,3,1,5,6,2,6,7,8]), array('name' => "第三名赛车手", 'places' => [2,3,2,5,7,10]), array('name' => "第四名赛车手", 'places' => [2,3,10,6,6,10]), array('name' => "第五个", 'places' => [2,3,2,5,7,10,1]), ); usort($racers, 函数($prev, $next) { //为每个赛车手订购位置 排序($prev['places']); 排序($next['places']); //比较每个地方 foreach ($prev['places'] AS $key => $prevRacerPlace) { // 如果所有值都相等,我们比较比赛的数量 if (!isset($next['places'][$key])) { 返回-1; } $nextRacerPlace = $next['places'][$key]; $diff = $prevRacerPlace - $nextRacerPlace; 如果 ($diff !== 0) { 返回$差异; } } // 如果所有值都相等,我们比较比赛的数量 if (count($next['places']) > count($prev['places'])) { 返回 1; } }); var_dump($racers);

【问题讨论】:

  • 你至少需要自己尝试解决这个问题..
  • @Darren,我试过了,但我不喜欢我的版本。这很麻烦。我将它添加到描述中。
  • 如果将数据转换成更容易使用的格式,可能会更容易,例如this for example..
  • @Darren 是array_count_values() 的一种,但它使算法更加复杂。根本不需要。

标签: php algorithm sorting


【解决方案1】:

在自定义排序之前做一些准备会很不错。所以我们避免了 lambda 函数中的嵌套排序:

foreach ($racers as $index => $racer) {
    $racers[$index]['sorted_places'] = $racer['places'];
    sort($racers[$index]['sorted_places']);
}

在排序 lambda 函数中,我们比较准备好的排序位置的头部并返回第一个定义的值。如果赛车手 B 排名第一的结果优于 A,则返回 1。如果赛车手 A 排名第一的结果优于 B ,返回-1。如果结果相同,则继续检查下一个排名靠前的位置。

usort($racers, function ($a, $b) {
    unset($value);
    do {
        $topA = array_shift($a['sorted_places']);
        $topB = array_shift($b['sorted_places']);

        if (is_null($topA) && is_null($topB)) {
            $value = 0;
        } elseif (is_null($topA)) {
            $value = 1;
        } elseif (is_null($topB)) {
            $value = -1;
        } elseif ($topA > $topB) {
            $value = 1;
        } elseif ($topA < $topB) {
            $value = -1;
        }
    } while (!isset($value));
    return $value;
});

【讨论】:

    【解决方案2】:

    这里还有一种算法,但我认为 Max Zuber 的解决方案效率更高。无论如何:

    通过array_count_values

    定义每个赛车手的位置
    foreach ($racers as &$racer) {
        $racer['number_places'] = array_count_values($racer['places']);
    }
    

    排序

    usort($racers, function($current, $next) {
    
        $next_places = $next['number_places'];
        $current_places = $current['number_places'];
    
        for ($i=1; $i<=max($next_places, $current_places); $i++) {
    
            if (!isset($current_places[$i]) && !isset($next_places[$i])) {
                continue;
            }
    
            if (!isset($current_places[$i])) {
                return 1;
            }
    
            if (!isset($current_places[$i]) 
                || $current_places[$i] > $next_places[$i])
            {
                return -1;
            }
        }
    });
    

    【讨论】:

      猜你喜欢
      • 2013-03-23
      • 2017-06-13
      • 2013-02-26
      • 2013-04-02
      • 2019-03-22
      • 1970-01-01
      • 2017-07-21
      • 2012-04-13
      • 1970-01-01
      相关资源
      最近更新 更多