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?