循环遍历多维数组并按分数

时间:2015-08-04 15:54:18

标签: php arrays multidimensional-array array-unset

我试图计算高尔夫球手在比赛中获胜的胜利顺序。

这些高尔夫比赛正在使用" stableford"积分评分系统,你获得最高分的每洞得分。与普通高尔夫球杆和中风比赛相比,#34;最低分数获胜的地方(虽然这也有倒计时系统,只计算平局时的最低分数...)

规则是使用"倒计时"。也就是说,如果在9洞之后得分,则最佳位置是最后8洞的最佳得分。然后是7洞等。

我能想到的最好的是2个阵列。

  1. 一个阵列,其中所有队员都参加了一轮比赛。 ($关系)
  2. 在所有9个洞中都有(参考数据库playerid)的满分数据。 ($ tie_perhole)
  3. 我遍历数组1,从数组2中提取数据并使用以下公式创建一个得分最高的临时数组:

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

    如果$ max只有1个项目,则此玩家是最高得分者。通过第一个数组的循环是"通过引用",所以在循环的下一次迭代中,他的playerid现在在数组中更长,因此被忽略。这种情况一直持续到第一个阵列中只剩下1个玩家。

    但是,只有在每次迭代中单个玩家获胜时才有效。不起作用的场景是,如果一组玩家与任何迭代/倒计数相关联。

    我认为我的问题是当前的结构我需要将原来的$ ties数组拆分,然后继续以相同的方式遍历拆分数组......

    作为一个例子......

    $ ties数组如下:

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

    $ tie_perhole(得分数据)数组如下:

    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分)得分最高,因此第1和第2应该在他们之间。玩家79应该是第6洞倒数第1名(14分,相比之下13分)。对于剩下的2名其他球员,第3名和第4名也应如此。

    此处可能会出现其他情况,因为在比赛中,可能会有很多不同数量的玩家(不同数量)通过排行榜处于不同的关联点。

    另请注意,排行榜上会有一些玩家未被束缚并保持现状。

    我的工作代码的基础是:

    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则获得第2分。在下一个并列组中,玩家73和1得到20分,玩家73将在第8洞倒计时赢得这一组并获得第3名(18分与17分相比),玩家1分在第4名。然后玩家26就是第5名。

    注意,$ tie_loop被添加到另一个数组以计算第1到第5位的结束位置,这样就可以了。

    希望这足以帮助。

1 个答案:

答案 0 :(得分:1)

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

<?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>";

好的......现在生病解释我的方法...... 既然我们需要知道得分最高并且它可能是关系,那么在单独的数组中维护所有内容是没有意义的,而我只是颠倒了

golfer =&gt;分数 Tota_score =&gt;高尔夫球手

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

现在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
        )

)