4

Good Evening - I am trying to create a multi-dimensional array based on an exploded text string of a account codes stored in the database. The account codes will be of varying lengths/depths. Say for example $test in the array below are similar to the results I would pull from the database:

$test = array( 
    '110|5100|120'    => 'Teacher Salaries',
    '110|5100|130'    => 'Other Professoinal Services',
    '110|5100|510|1'  => 'Primary Supplies',
    '110|5100|510|2'  => 'Intermediate Supplies', 
    '110|7300|110'    => 'Administrator Salaries', 
    '110|7300|510'    => 'Administrative Supplies', 
    '763|5100'        => 'Academic Grants'
); 
foreach($test AS $k => $v) { 
    $lvl = explode("|", $k);
    // Not sure what to do next... 
}

What I want to do is create a function which will return an array such as the following:

[110] => Array
    (
        [5100] => Array
            (
                [120] => Teacher Salaries
                [130] => Other Professional Services
                [510] => Array
                    (
                        [1] => Primary Supplies
                        [2] => Intermediate Supplies
                    )
            )
        [7300] => Array
            (
                [110] => Administrator Salaries
                [510] => Supplies
            )
    )
[763] => Array
    (
        [5100] => Academic Grants
    )

I was able to come up with a function that can take a single one of the codes and break it down correctly into an array, but when I try to merge them together, they lose their keys. Here is what I have so far:

function expandedArray($codes, $value) { 
    $decoded = explode("|",$codes);
    RETURN expandedArraySub($decoded, $value); 
}
function expandedArraySub($decoded = array(), $value = Null) { 
    $k = array_pop($decoded); 
    $out[$k] = $value;
    if(is_array($decoded) && count($decoded) > 0) { $out = expandedArraySub($decoded, $out); }
    RETURN $out;
}

But when I run the following, instead of getting what I want as described above, I get an array that loses the "110" key:

$r1 = expandedArray('110|5100|510|1', "Primary Supplies"); 
  // $r1 is now [ 110 => [5100 => [510 => [ 1 ] ] ] ]
$r2 = expandedArray('110|5100|510|2', 'Intermediate Supplies'); 
  // $r2 is now [ 110 => [5100 => [510 => [ 2 ] ] ] ]
$r = array_merge($r1, $r2); 

The results I get remove the first key and doesn't combine the results as I was hoping. Here is what I get:

[0] => Array
    (
        [5100] => Array
            (
                [510] => Array
                    (
                        [1] => Primary Supplies
                    )
            )
    )
[1] => Array
    (
        [5100] => Array
            (
                [510] => Array
                    (
                        [2] => Intermediate Supplies
                    )
            )
    )

Any help is much appreciated! Thanks!

1
  • The behavior of array_merge() with numeric keys is as documented and sadly there are no options to change it. If you want to keep all your hard work, try something like $out['x'.$k] = $value; in expandedArraySub. This will force array_merge to treat your keys as strings. I think you also want array_merge_recursive() instead of array_merge. Of course you need to get rid of all the x's, but that should be simpler and the work is all yours. Commented Sep 5, 2017 at 4:04

1 Answer 1

1

Try this code:

function getVal($data,$chain){
    $level = $data;
    for($i=0;$i<count($chain);$i++){
        if(isset($level[$chain[$i]]))
            $level = $level[$chain[$i]];
        else
            return null; // key does not exist, return null
    }
    return $level;
}

function setVal(&$data,$chain,$value){
    $level = &$data;
    for($i=0;$i<count($chain);$i++){
        $level = &$level[$chain[$i]]; // set reference (&) in order to change the value of the object
    }
    $level = $value;
}

For setting use it like this:

$output = array();
$test = array( 
    '110|5100|120'    => 'Teacher Salaries',
    '110|5100|130'    => 'Other Professoinal Services',
    '110|5100|510|1'  => 'Primary Supplies',
    '110|5100|510|2'  => 'Intermediate Supplies', 
    '110|7300|110'    => 'Administrator Salaries', 
    '110|7300|510'    => 'Administrative Supplies', 
    '763|5100'        => 'Academic Grants'
); 
foreach($test AS $k => $v) { 
    $lvl = explode("|", $k);
    setVal($output,$lvl,$v); 
}

$output should have the desired format.

Read more about this code in my previous post

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.