Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I was browsing Stack Overflow recently and saw a PHP question about rearranging an array of arrays for printing. The initial data structure looked like this:

$array1 = array(
    array("type01",1995),
    array("type03",1996),
    array("type01",1995),
    array("type09",1998),
    array("type09",1995),
    array("type02",1997),
    array("type01",1995),
    array("type02",1999),
    array("type09",1995)
);

For printing, the number of occurrences of each pairing--type and year--had to be counted and a table of frequencies made with type as columns and the years as the rows, i.e.

Year    type01    type02    type03    type09
1995    3         0         0         2
1996    0         0         1         0
1997    0         1         0         0
1998    0         0         0         1
1999    0         1         0         0

(the actual table formatting was not critical)

Someone else answered the question, and used the following code:

$sorted = array();
$types = array();
array_walk($array1, function($v) use (&$sorted, &$types){
   if( !isset($sorted[$v[1]]) )
       $sorted[$v[1]] = array();
   $sorted[$v[1]][] = $v[0];
   $types[] = $v[0];
});

// filter types
$types = array_unique($types);
sort($types);

// sort year
ksort($sorted);

echo '----' . implode(' ,', $types) . "\r\n";
foreach($sorted as $year => $data)
{    echo $year . ' - ';
    $count = array_count_values($data);

   foreach($types as $type)
   {  
      if( !isset($count[$type]))
      {
          echo '0,';
      } else {
          echo $count[$type].',';
      }
   }
   echo "\r\n";
}

I come from a Perl background, and I would use the following code to solve the problem:

$finalArray = array();
$years = array();

foreach ($array1 as $ix) {
    // $ix[0] is typeNN, $ix[1] is year.
    // index by type and then year.
    // the accumulator will count the number per type per year
    $finalArray[ $ix[0] ][ $ix[1] ]++;
    // keep an array of years
    $years[ $ix[1] ]++;
}

// sort arrays by key
ksort($finalArray);
ksort($years);

// print out the column headings
echo "Year\t" . implode("\t", array_keys($finalArray) ) . "\n";

// now add the data
foreach (array_keys($years) as $y) {
    echo $y;
    // for each type, check the frequency for the year
    // print '0' if the year does not exist
    foreach ($finalArray as $type => $year) {
        if (array_key_exists($y, $year)) {
            echo "\t" . $year[$y];
        } else {
            echo "\t0";
        }
    }
    echo "\n";
}

Granted, the two pieces of code format the table slightly differently, but is one approach "better"--more efficient, more in line with standard PHP coding practices--than the other?

I'm also aware that my code generates notices about undefined index/offsets because I'm used to Perl's autovivification of data structures. Is this something to worry about or not?

share|improve this question
1  
I wouldn't worry too much about notices, it won't effect the behaviour of your code, it is just there to help you find errors. To remove them you would likely need to do isset($val) first before using it. –  bumperbox Sep 6 '14 at 7:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.