Mustapha Ghazali Mustapha Ghazali - 3 months ago 10
PHP Question

Flat array to a hierarchical multi-dimensional array

I have an flat array that looks like this exemple :

array (
0 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '1',
'@NAME' => '[CDATA[nomenclature exemple]]',
'@LEVEL' => '0',
),
),
1 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '3',
'@NAME' => '[CDATA[droit]]',
'@LEVEL' => '1',
),
),
2 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '13',
'@NAME' => '[CDATA[législation]]',
'@LEVEL' => '2',
),
),
3 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '14',
'@NAME' => '[CDATA[statuts]]',
'@LEVEL' => '3',
),
),
4 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '15',
'@NAME' => '[CDATA[projets de loi]]',
'@LEVEL' => '4',
),
),
5 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '16',
'@NAME' => '[CDATA[réglementations]]',
'@LEVEL' => '2',
),
),
6 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '17',
'@NAME' => '[CDATA[instruments statutaires]]',
'@LEVEL' => '3',
),
),
7 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '2',
'@NAME' => '[CDATA[économie]]',
'@LEVEL' => '1',
),
),
8 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '8',
'@NAME' => '[CDATA[analyse cout-avantage]]',
'@LEVEL' => '2',
),
),
9 =>
array (
'TreePad_Fields' =>
array (
'@ID' => '6',
'@NAME' => '[CDATA[analyse socio-économique]]',
'@LEVEL' => '2',
),
),
)


and I would like to have like this :

$data = array(
'[CDATA[nomenclature exemple]]' => array(
'[CDATA[droit]]' => array(
'[CDATA[législation]]' => array(
'[CDATA[statuts]]' => array(
'[CDATA[projets de loi]]'
),
),
'[CDATA[réglementations]]' => array(
'[CDATA[instruments statutaires]]'
),
),
'[CDATA[économie]]' => array(
'[CDATA[analyse cout-avantage]]',
'[CDATA[analyse socio-économique]]',

),
)
);


I can't figure out how to do it. I've found other examples here for converting flattened arrays into multidimensional ones but not where there's a custom child like this.

Answer

I should say it is a bit inconsistent to want to have the leaves in the datastructure have the [CDATA...] name as value of an indexed array, while in the rest of the tree they are keys.

So, I would suggest to make those leaves also keyed by the [CDATA...] name, but just with an empty array as value. That way the structure is consistent throughout.

For that structure you could use this function:

function buildTree($data) {
    foreach($data as $i => $row) {
        $arr = $row['TreePad_Fields'];
        $level = $arr['@LEVEL'];
        $key = $arr['@NAME'];
        $levels[$level][$key] = [];
        $levels[$level+1] = &$levels[$level][$key];
    }
    return $levels[0];
}

Call it like this:

$result = buildTree($data);

For the sample data given, the result would be:

array (
  '[CDATA[nomenclature exemple]]' => array (
    '[CDATA[droit]]' => array (
      '[CDATA[législation]]' => array (
        '[CDATA[statuts]]' => array (
          '[CDATA[projets de loi]]' => array (),
        ),
      ),
      '[CDATA[réglementations]]' => array (
        '[CDATA[instruments statutaires]]' => array (),
      ),
    ),
    '[CDATA[économie]]' => array (
      '[CDATA[analyse cout-avantage]]' => array (),
      '[CDATA[analyse socio-économique]]' => array (),
    ),
  ),
)

See it run on eval.in

Comments