Transforming an array into multilevel array (PHP)

In PHP there is function array_combine(). This function may not work as expected in the case if a key is met more than once. For this reason, I created the following function:

function array_combine_array($keyname, $array) {
  $ret = array();
  foreach($array as $value) {
    $key = $value[$keyname];
    if(!isset($ret[$key])) $ret[$key] = array();
    array_push($ret[$key], $value);
  }
  return $ret;
}

This function behaves like array_combine() but in its result to every key corresponds an array of values not single value, and this array has exactly the number of elements equal to the number of key occurrences.

To make a step forward, I create a function array_combine_multilevel() which, given an array of associative arrays and an array of keys, creates a multi-level associative array indexed by values of these keys (the first key in the list becomes the outer key in the output associative array, the next key becomes an index in the enclosed array, etc.)

To understand this see the example:

print_r(array_combine_multilevel(array('a', 'b'),
                                 array(array('a'=>1, 'b'=>2, 'c'=>5), array('a'=>1, 'b'=>2, 'c'=>6), array('a'=>3, 'b'=>4, 'c'=>7))));

outputs:

Array
(
    [1] => Array
        (
            [2] => Array
                (
                    [0] => Array
                        (
                            [a] => 1
                            [b] => 2
                            [c] => 5
                        )

                    [1] => Array
                        (
                            [a] => 1
                            [b] => 2
                            [c] => 6
                        )

                )

        )

    [3] => Array
        (
            [4] => Array
                (
                    [0] => Array
                        (
                            [a] => 3
                            [b] => 4
                            [c] => 7
                        )

                )

        )

)

The code for the function array_combine_multilevel():

abstract class FixedDepthTreeTraverser {
  public function traverse(&$tree, $depth) {
    if($depth == 0)
      $this->on_leaf($tree);
    else
      foreach($tree as &$node)
        $this->traverse($node, $depth-1);
  }
  
  abstract protected function on_leaf(&$node);
}

class ArrayCombineTraverser extends FixedDepthTreeTraverser {
  private $keyname;
  
  public function __construct($keyname) {
    $this->keyname = $keyname;
  }
  
  protected function on_leaf(&$node) {
    $node = array_combine_array($this->keyname, $node);
  }
}

// if $keynames == array('a', 'b') then it generates a hash like array('a'=>array('b'=>...))
function array_combine_multilevel($keynames, $array) {
  if(!is_array($keynames)) $keynames = array($keynames);
  $ret = $array;
  for($i=0; $i<count($keynames); ++$i) {
    $keyname = $keynames[$i];
    $worker = new ArrayCombineTraverser($keyname);
    $worker->traverse($ret, $i);
  }
  return $ret;
}
Advertisements
This entry was posted in Programming and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s