Php 按地点对参赛者/运动员进行分类

Php 按地点对参赛者/运动员进行分类,php,algorithm,sorting,Php,Algorithm,Sorting,我有一些赛车手的数据,如下表所示: 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]) ... ) 排列( 数组(name=>“第一赛车手”,places=>[1,3,1,5,6,2,6,7,8]), 数组(name=>“第二名赛车手”

我有一些赛车手的数据,如下表所示:

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]) ... ) 排列( 数组(name=>“第一赛车手”,places=>[1,3,1,5,6,2,6,7,8]), 数组(name=>“第二名赛车手”,places=>[2,4,2,5,7]) ... ) 建议对它们进行分类的最佳方式,以便第一批参赛者拥有更好的位置。例如,如果第一名选手至少有一个第一名,而另一个没有,那么第一名在列表中的位置会更高。如果他们都有第一名,比较第一名的数量。如果数字也相等,则比较第二位,依此类推

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

$racers=阵列( 数组('name'=>“first racer”,'places'=>[1,3,1,5,6,2,6,7,8,9]), 数组('name'=>“第二名赛车手”,'places'=>[1,3,1,5,6,2,6,7,8]), 数组('name'=>“第三名赛车手”,'places'=>[2,3,2,5,7,10]), 数组('name'=>“第四名赛车手”,'places'=>[2,3,10,6,6,10]), 数组('name'=>“thefifth”,'places'=>[2,3,2,5,7,10,1]), ); usort($racers,function($prev,$next){ //为每位参赛者定座 排序($prev['places']); 排序($next['places'); //把每个地方相互比较一下 foreach($prev['places']作为$key=>$prevRacerPlace){ //如果所有的值都相等,我们比较种族的数量 如果(!isset($next['places'][$key])){ 返回-1; } $nextRacerPlace=$next['places'][$key]; $diff=$prevRacerPlace-$nextRacerPlace; 如果($diff!==0){ 返回$diff; } } //如果所有的值都相等,我们比较种族的数量 如果(计数($next['places'))>count($prev['places')){ 返回1; } }); var_dump(赛车手);
在定制分拣之前做一些准备将是一个非常好的选择。因此,我们在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;
});
usort($racers,function($a,$b){
未结算(价值);
做{
$topA=array_shift($a['sorted_places']);
$topB=数组移位($b['sorted\u places']);
if(is_null($topA)和&is_null($topB)){
$value=0;
}elseif(为空($topA)){
$value=1;
}elseif(为空($topB)){
$value=-1;
}elseif($topA>topB){
$value=1;
}elseif($topA<$topB){
$value=-1;
}
}而(!isset($value));
返回$value;
});

在定制排序之前做一些准备将是一个非常好的选择。因此,我们在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;
});
usort($racers,function($a,$b){
未结算(价值);
做{
$topA=array_shift($a['sorted_places']);
$topB=数组移位($b['sorted\u places']);
if(is_null($topA)和&is_null($topB)){
$value=0;
}elseif(为空($topA)){
$value=1;
}elseif(为空($topB)){
$value=-1;
}elseif($topA>topB){
$value=1;
}elseif($topA<$topB){
$value=-1;
}
}而(!isset($value));
返回$value;
});

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

通过数组\u计数\u值定义每个参赛者的位置

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;
        }
    }
});
usort($racers,function($current,$next){
$next_places=$next['number_places'];
$current_places=$current['number_places'];
对于($i=1;$i$next_places[$i])
{
返回-1;
}
}
});

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

通过数组\u计数\u值定义每个参赛者的位置

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;
        }
    }
});
usort($racers,function($current,$next){
$next_places=$next['number_places'];
$current_places=$current['number_places'];
对于($i=1;$i$next_places[$i])
{
返回-1;
}
}
});

你至少需要自己尝试解决这个问题。@Darren,我尝试过,但我不喜欢我的版本。这很麻烦。我把它添加到了description中。如果你把数据转换成一种更容易使用的格式,比如@Darren,可能会更容易,它是一种
数组\u count\u values()
,但它会使算法更加复杂。根本不需要。你至少需要自己尝试解决这个问题。@Darren,我尝试过,但我不喜欢我的版本。这很麻烦。我把它添加到了description中。如果你把数据转换成一种更容易使用的格式,比如@Darren,可能会更容易,它是一种
数组\u count\u values()
,但它会使算法更加复杂。根本不需要。