循环遍历多维数组并按分数排序子数组



我正在尝试计算高尔夫球手在比赛中平局时的获胜顺序。

这些高尔夫比赛使用"stableford"计分系统,你每洞得分,得分最高的获胜。与一般的高尔夫"杆数比赛"相比,最低杆数获胜(尽管这也有计数系统,只计算平局时的最低杆数…)

规则是使用"countback"。也就是说,如果在9洞之后比分持平,那么最好的位置就是最后8洞的最好成绩。然后7个孔,等等

我能想到的最好的是2个数组。

  1. 一个数组,其中包含在给定回合中并列的所有玩家。(关系)
  2. 拥有所有9洞的完整得分数据(参考数据库playerid)的一个。(tie_perhole美元)

我循环遍历数组1,从数组2中提取数据,并使用以下公式创建得分最高的临时数组:

$max = array_keys($array,max($array));

如果$max只有1件物品,这个玩家是最高的得分者。通过第一个数组的循环是"通过引用",所以在循环的下一次迭代中,他的playerid现在在数组中更长,因此被忽略。直到第一个数组中只剩下1个playerid为止。

然而,它只有在每次迭代中都有一个玩家获胜时才有效。如果一组玩家在任何迭代/回滚上绑定,那么这种情况就行不通了。

我认为我的问题是我目前的结构需要原来的$ties数组被分割,然后继续以同样的方式迭代分割数组…

作为一个例子…

$ties数组如下:

Array 
( 
    [18] => Array 
        ( 
            [0] => 77 
            [1] => 79 
            [2] => 76 
            [3] => 78 
        ) 
)

$tie_perhole (score data)数组如下:

Array 
( 
    [18] => Array 
        ( 
            [77] => Array 
                ( 
                    [9] => 18 
                    [8] => 16 
                    [7] => 14 
                    [6] => 12 
                    [5] => 10 
                    [4] => 8 
                    [3] => 6 
                    [2] => 4 
                    [1] => 2 
                ) 
            [79] => Array 
                ( 
                    [9] => 18 
                    [8] => 17 
                    [7] => 15 
                    [6] => 14 
                    [5] => 11 
                    [4] => 9 
                    [3] => 7 
                    [2] => 5 
                    [1] => 3 
                ) 
            [76] => Array 
                ( 
                    [9] => 18 
                    [8] => 16 
                    [7] => 14 
                    [6] => 12 
                    [5] => 10 
                    [4] => 8 
                    [3] => 6 
                    [2] => 4 
                    [1] => 2 
                ) 
            [78] => Array 
                ( 
                    [9] => 18 
                    [8] => 17 
                    [7] => 15 
                    [6] => 13 
                    [5] => 11 
                    [4] => 9 
                    [3] => 7 
                    [2] => 5 
                    [1] => 3 
                ) 
        ) 
) 

所以在这场比赛中,78号和79号球员在第8洞的倒数赛中得分最高(17分),所以第一名和第二名应该在他们之间。79号球员在第6洞的倒数中应该是第一名(14分,对13分)。对于第三名和第四名,剩下的两名选手也应如此。

这里还可能发生其他情况,在比赛中,可能会有许多组玩家(数量不同)在排行榜上获得不同的积分。

还要注意的是,排行榜上会有一些玩家没有并列,而是保持在他们目前的位置。

我所拥有的基本工作代码是:

foreach ($ties as $comparekey => &$compareval) {
$tie_loop = 0;
for ($m = 9; $m >= 1; $m--) {
    $compare = array();
    foreach ($compareval as $tie) {
        $compare[$tie] = $tie_perhole[$comparekey][$tie][$m];
    }
    $row = array_keys($compare,max($compare));
    if (count($row) == 1) {
        $indexties = array_search($row[0], $ties[$comparekey]);
        unset($ties[$comparekey][$indexties]);
        // Now update this "winners" finishing position in a sorted array
        // This is a multidimensional array too, with custom function...
        $indexresults = searchForId($row[0], $comp_results_arr);
        $comp_results_arr[$indexresults][position] = $tie_loop;
        $tie_loop++;
    }
    // I think I need conditions here to filter if a subset of players tie
    // Other than count($row) == 1
    // And possibly splitting out into multiple $ties arrays for each thread...
    if (empty($ties[$comparekey])) {
        break;
    }
}
}
usort($comp_results_arr, 'compare_posn_asc');
foreach($comp_results_arr as $row) {
    //echo an HTML table...
}

提前感谢任何有用的见解,提示,想法等…

Robert Cathay要求更多的场景。这是另一个…

排行榜实际上有更多的参赛者(玩家26有一个糟糕的回合…),但我需要帮助的代码只关心排行榜内的关系。

总结排行榜:

Points  Player
21      48
21      75
20      73
20      1
13      26

这个例子生成了一个$tie_perhole数组:

Array 
( 
    [21] => Array 
        ( 
            [75] => Array 
                ( 
                    [9] => 21 
                    [8] => 19 
                    [7] => 16 
                    [6] => 14 
                    [5] => 12 
                    [4] => 9 
                    [3] => 7 
                    [2] => 5 
                    [1] => 3 
                ) 
            [48] => Array 
            ( 
                [9] => 21 
                [8] => 19 
                [7] => 16 
                [6] => 13 
                [5] => 11 
                [4] => 9 
                [3] => 8 
                [2] => 5 
                [1] => 3 
            ) 
    ) 
[20] => Array 
    ( 
        [73] => Array 
            ( 
                [9] => 20 
                [8] => 18 
                [7] => 16 
                [6] => 13 
                [5] => 11 
                [4] => 8 
                [3] => 6 
                [2] => 5 
                [1] => 3 
            ) 
        [1] => Array 
            ( 
                [9] => 20 
                [8] => 17 
                [7] => 16 
                [6] => 14 
                [5] => 12 
                [4] => 9 
                [3] => 7 
                [2] => 4 
                [1] => 2 
            ) 
    ) 
) 

在这个例子中,数组显示球员75和48得到21分,球员75最终将在第6洞的倒数中获胜(14分对13分),球员48是第二名。在第二组比赛中,73号和1号选手各得20分,73号选手将在第8洞的倒数击球中获胜,获得第3名(18分),1号选手获得第4名。球员26是第5名。

注意,$tie_loop被添加到另一个数组中来计算第一到第五名的结束位置,所以它是工作的。

好吧,我根本不懂高尔夫…哈哈哈但是!我想我了解了这个问题的要点,所以这是我的解决方案。

<?php
/**
* Author    : Carlos Alaniz
* Email     : Carlos.glvn1993@gmail.com
* Porpuse   : Stackoverflow example
* Date      : Aug/04/2015
**/

$golfers = [
"A" => [1,5,9,1,1,2,3,4,9],
"B" => [2,6,4,2,4,4,1,9,3],
"C" => [3,4,9,8,1,1,5,1,3],
"D" => [1,5,1,1,1,5,4,5,8]
];
//Iterate over scores.
function get_winners(&$golfers, $hole = 9){
    $positions = array();                               // The score numer is the key!
    foreach ($golfers as $golfer=>$score ) {            // Get key and value
        $score_sub = array_slice($score,0,$hole);       // Get the scores subset, first iteration is always all holes
        $total_score = (string)array_sum($score_sub);   // Get the key 
        if(!isset($positions[$total_score])){
            $positions[$total_score] = array();         // Make array
        }
        $positions[$total_score][] = $golfer;           // Add Golpher to score.
    }
    ksort($positions, SORT_NUMERIC);                    // Sort based on key, low -> high
    return array(end($positions), key($positions));     // The last shall be first
}
//Recursion is Awsome
function getWinner(&$golfers, $hole = 9){
    if ($hole == 0) return;
    $winner = get_winners($golfers,$hole);              // Get all ties, if any.
    if(count($winner[0]) > 1){                          // If theirs ties, filter again!
        $sub_golfers = 
        array_intersect_key($golfers, 
            array_flip($winner[0]));                    // Only the Worthy Shall Pass.
        $winner = getWinner($sub_golfers,$hole - 1);    // And again...
    }
    return $winner;                                     // We got a winner, unless they really tie... 
}
echo "<pre>";
print_R(getWinner($golfers));
echo "</pre>";

好吧…现在我来解释一下我的方法……因为我们需要知道最高分,而且它可能是平手,所以在单独的数组中维护所有这些对我来说是没有意义的,所以我只是颠倒了

高尔夫球手=>分数Tota_score =>高尔夫球手

这样我们就可以按键对数组进行排序,并获得所有得分最高的高尔夫球手。

现在total_score是洞分数数组的一个子集的总和。所以…当这个函数第一次运行时,它将添加所有9个洞,在本例中有3个高尔夫球手最终获得相同的分数。

Array
(
    [0] => Array
        (
            [0] => A
            [1] => B
            [2] => C
        )
    [1] => 35
)

由于高尔夫球手总数不是1,我们仍然在第9洞,我们再次运行这个,但这次只针对这3个高尔夫球手和当前洞- 1,所以我们这次只加到第8洞。

Array
(
    [0] => Array
        (
            [0] => B
            [1] => C
        )
    [1] => 32
)

我们有另一个平局....这个过程将一直持续,直到我们到达最后一个洞,或者获胜者。

Array
(
    [0] => Array
        (
            [0] => C
        )
    [1] => 31
)

编辑

<?php
/**
* Author    : Carlos Alaniz
* Email     : Carlos.glvn1993@gmail.com
* Porpuse   : Stackoverflow example
**/

$golfers = [
"77" => [2,4,6,8,10,12,14,16,18],
"79" => [3,5,7,9,11,14,15,17,18],
"76" => [2,4,6,8,10,12,14,16,18],
"78" => [3,5,7,9,11,13,15,17,18]
];
//Iterate over scores.
function get_winners(&$golfers, $hole = 9){
    $positions = array();                               // The score numer is the key!
    foreach ($golfers as $golfer => $score) {            // Get key and value
        //$score_sub = array_slice($score,0,$hole);     // Get the scores subset, first iteration is always all holes
        $total_score = (string)$score[$hole-1];         // Get the key 
        if(!isset($positions[$total_score])){
            $positions[$total_score] = array();         // Make array
        }
        $positions[$total_score][] = $golfer;           // Add Golpher to score.
    }
    ksort($positions, SORT_NUMERIC);                    // Sort based on key, low -> high
    return [
            "winner"=> end($positions),
            "score" => key($positions),
            "tiebreaker_hole"  => [
                "hole"=>$hole,
                "score"=> key($positions)],
            ];                                          // The last shall be first
}
//Recursion is Awsome
function getWinner(&$golfers, $hole = 9){
    if ($hole == 0) return;
    $highest = get_winners($golfers,$hole);             // Get all ties, if any.
    $winner = $highest;
    if(count($winner["winner"]) > 1){                   // If theirs ties, filter again!
        $sub_golfers = 
        array_intersect_key($golfers, 
            array_flip($winner["winner"]));             // Only the Worthy Shall Pass.
        $winner = getWinner($sub_golfers,$hole - 1);    // And again...
    }
    $winner["score"] = $highest["score"];
    return $winner;                                     // We got a winner, unless they really tie... 
}
echo "<pre>";
print_R(getWinner($golfers));
echo "</pre>";
结果:

Array
(
    [winner] => Array
        (
            [0] => 79
        )
    [score] => 18
    [tiebreaker_hole] => Array
        (
            [hole] => 6
            [score] => 14
        )
)

相关内容

  • 没有找到相关文章

最新更新