我有一些以下列形式呈现的赛车手的数据:
array( array(name => "the first racer", places => [1,3,1,5,6,2,6,7,8]), array(name => "the second racer", places => [2,4,2,5,7]) ... )
建议对它们进行排序的最佳方法,以便第一批参赛选手有更好的位置。例如,如果第一个赛车至少有一个第一名而另一个没有,则第一个在列表中更高。如果他们都有第一名,请比较第一名的数量。如果数字相等,则比较第二个位置,依此类推。
我的解决方案(它看起来不太优雅。也许它可以以某种方式更轻松地完成):
$racers = array( array('name' => "the first racer", 'places' => [1,3,1,5,6,2,6,7,8,9]), array('name' => "the second racer", 'places' => [1,3,1,5,6,2,6,7,8]), array('name' => "the third racer", 'places' => [2,3,2,5,7,10]), array('name' => "the fourth racer", 'places' => [2,3,10,6,6,10]), array('name' => "the fifth", 'places' => [2,3,2,5,7,10,1]), ); usort($racers, function($prev, $next) { // order places for every racer sort($prev['places']); sort($next['places']); //compare each place with each other foreach ($prev['places'] AS $key => $prevRacerPlace) { // if all values are equal, we compare the number of races if (!isset($next['places'][$key])) { return -1; } $nextRacerPlace = $next['places'][$key]; $diff = $prevRacerPlace - $nextRacerPlace; if ($diff !== 0) { return $diff; } } // if all values are equal, we compare the number of races if (count($next['places']) > count($prev['places'])) { return 1; } }); var_dump($racers);
答案 0 :(得分:3)
在自定义排序之前做一些准备工作会很不错。所以我们避免在lambda函数中嵌套排序:
foreach ($racers as $index => $racer) {
$racers[$index]['sorted_places'] = $racer['places'];
sort($racers[$index]['sorted_places']);
}
在对lambda函数进行排序时,我们比较准备好的排序位置的头部并返回第一个定义的值。如果racer B 排名靠前的结果优于 A ,则返回1.如果racer 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;
});
答案 1 :(得分:1)
这是另一种算法,但我认为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;
}
}
});