2009-04-03 5 views
4

Ich habe eine Reihe von Objekten, ähnlich wie die weiter unten definiert:A „Kreuztabellen-“ oder „Drehpunkt“ -Tabelle aus einem Array in PHP Aufbau

$scores = array(); 

// Bob round 1 
$s = new RoundScore(); 
$s->Round_Name = 'Round 1'; 
$s->Player_Name = 'Bob'; 
$s->Score = 10; 
$scores[0] = $s; 

// Bob round 2 
$s = new RoundScore(); 
$s->Round_Name = 'Round 2'; 
$s->Player_Name = 'Bob'; 
$s->Score = 7; 
$scores[1] = $s; 

// Jack round 1 
$s = new RoundScore(); 
$s->Round_Name = 'Round 1'; 
$s->Player_Name = 'Jack'; 
$s->Score = 6; 
$scores[2] = $s; 

// Jack round 2 
$s = new RoundScore(); 
$s->Round_Name = 'Round 2'; 
$s->Player_Name = 'Jack'; 
$s->Score = 12; 
$scores[3] = $s; 

Wenn I Schleife durch und Dump das $scores Objekt in eine Tabelle, es wird in etwa so aussehen:

 
Round_Name Player Score 
---------------------------- 
Round 1  Bob  10 
Round 2  Bob   7 
Round 1  Jack  6 
Round 2  Jack  12 

Was ich will, aber so etwas wie dies:

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

Ich werde nicht im Voraus wissen, wie viele Runden oder Spieler es gibt und sagen wir einfach, dass ich die Art, wie die Objekte gebaut werden, nicht ändern kann.

Was ist der effizienteste Weg, dies in PHP zu tun?

+0

Ich denke, Sie haben einen Tippfehler. Für Bob Runde 2 haben Sie: "$ Runden [1] = $ s;" anstelle von: "$ scores [1] = $ s;" – maxyfc

+0

Danke, du hast Recht - ich habe es jetzt behoben :) – Damovisa

Antwort

2

Wenn wir das annehmen:

  • die Reihenfolge, in der Anordnung von Noten ist der Name immer in der Reihenfolge von Spieler und dann durch die runde Zahl
  • die Zahl der Runden ist für jeden Spieler

Dann gleiche tun wir jeder Spieler Partitur drucken, was als wir durch das Feld bewegt, während die Summe in den Prozess der Berechnung aber wenn wir sehen, einen neuen Spieler zurückzusetzen:

$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; 
} 

Beispielausgabe:

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

Dies sollte sehr effizient sein, weil es nur einmal durch das Feld geht.

+0

Danke, das sieht ziemlich effizient aus ... – Damovisa

6

Soweit ich sagen kann, PHP-Arrays sind als Hash-Tabellen implementiert (so Lookup/Update sollte ziemlich effizient sein) Wird Zeit Effizienz sogar ein Problem sein, überhaupt?

Ich würde es nur tun, um den „einfachen“ Weg:

$table = array(); 
$round_names = array(); 
$total = array(); 

foreach ($scores as $score) 
{ 
    $round_names[] = $score->Round_Name; 
    $table[$score->Player_Name][$score->Round_Name] = $score->score; 
    $total[$score->Player_Name] += $score->score; 
} 

$round_names = array_unique($round_names); 

foreach ($table as $player => $rounds) 
{ 
    echo "$player\t"; 
    foreach ($round_names as $round) 
     echo "$rounds[$round]\t"; 
    echo "$total[$player]\n"; 
} 

(Ich weiß, dass der Arrays nicht richtig initialisiert, aber Sie erhalten die Idee)

+0

Ich habe diese Antwort eher als die von maxyfc geupdated, weil sie viel einfacher und robuster ist. Ich sehe Leistung hier eigentlich nicht als Engpass; die Wartbarkeit des Codes ist wichtiger. Wahrscheinlich wirst du auch einen 'natsort ($ round_names)' btw machen wollen. – Zecc

+0

Warum hast du foreach ($ round_names als $ round) echo-Runden [$ round] \ t "verwendet; statt foreach ($ rounds als $ round) echo $ round – sanu