Building a “crosstab” or “pivot” table from an array in php

后端 未结 2 1328
暖寄归人
暖寄归人 2021-01-06 06:14

I have an array of objects defined similarly to the below:

$scores = array();

// Bob round 1
$s = new RoundScore();
$s->Round_Name = \'Round 1\';
$s->         


        
2条回答
  •  灰色年华
    2021-01-06 06:59

    If we can assume that:

    • the order of scores in the array is always in the order by player's name and then by the round number
    • the number of rounds is same for each player

    Then, what we can do is print each player's score as we moved through the array while calculating the total in the process but resetting it if we see a new player:

    $round_count = 0;
    $header_printed = false;
    $current_player = NULL;
    $current_total = 0;
    $current_output_line = "";
    foreach ($scores as $score) {
        // Check whether we have to move to a new player
        if ($score->Player_Name != $current_player) {
            // Check whether we have anything to print before
            // resetting the variables
            if (!is_null($current_player)) {
                if (!$header_printed) {
                    printf("%-10s", "Player");
                    for ($i = 0; $i < $round_count; $i++) {
                        printf("%-10s", "Round $i");
                    }
                    printf("%-10s\n", "Total");
    
                    $header_printed = true;
                }
    
                $current_output_line .= sprintf("%5d\n", $current_total);
                print $current_output_line;
            }
    
            // Reset the total and various variables for the new player
            $round_count = 0;
            $current_player = $score->Player_Name;
            $current_total = 0;
            $current_output_line = sprintf("%-10s", $score->Player_Name);
        }
    
        $round_count++;
        $current_total += $score->Score;
        $current_output_line .= sprintf("%5d     ", $score->Score);
    }
    // The last player is not printed because we exited the loop 
    // before the print statement, so we need a print statement here.
    if ($current_output_line != "") {
        $current_output_line .= sprintf("%5d\n", $current_total);
        print $current_output_line;
    }
    

    Sample output:

    Player    Round 0   Round 1   Total
    Bob          10         7        17
    Jack          6        12        18
    

    This should be quite efficient because it only goes through the array once.

提交回复
热议问题