2009-04-03 1 views
4

У меня есть массив объектов определяется аналогично ниже:Построение «перекрестный» или «Стержень» таблицу из массива в PHP

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

, если я цикл через и сбросить $scores объект в таблицу, это будет выглядеть примерно так:

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

то, что я хочу, однако, что-то вроде этого:

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

Я не буду заранее знать, сколько раундов или игроков будет, и давайте просто скажем, что я не могу изменить способ построения объектов.

Каков наиболее эффективный способ сделать это в php?

+0

У меня есть опечатка. Для Боба 2 раунда у вас есть: «$ rounds [1] = $ s;» вместо: "$ score [1] = $ s;" – maxyfc

+0

Спасибо, ты прав. Я исправил это сейчас. – Damovisa

ответ

2

Если мы можем предположить, что:

  • порядок оценки в массиве всегда в порядке по имени игрока , а затем круглого числа
  • число раунды же для каждого игрока

Тогда, что мы можем сделать, это распечатать счет каждого игрока, как мы переехали через массив при расчете общего в процессе, но сбросить его, если мы видим новый игрок:

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

Пример вывода:

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

Это должно быть весьма эффективным, поскольку он идет только через массив один раз.

+0

Спасибо, это выглядит довольно эффективно ... – Damovisa

6

Насколько я могу судить, массивы PHP реализованы в виде хеш-таблиц (так что поиск/обновление должно быть довольно эффективным) Будет ли эффективность во времени даже проблемой, во всяком случае?

Я бы просто сделать это «простой» способ:

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

(Я знаю, что массивы не инициализирован, но вы получите идею)

+0

Я вернул этот ответ, а не maxyfc, потому что он намного проще и надежнее. Я действительно не вижу, чтобы производительность была узким местом здесь; надежность кода более важна. Вероятно, вы также захотите сделать 'natsort ($ round_names)' btw. – Zecc

+0

Почему вы использовали foreach ($ round_names как $ round) эхо раундов [$ round] \ t "вместо foreach ($ rounds as $ round) echo $ round – sanu

 Смежные вопросы

  • Нет связанных вопросов^_^