views:

51

answers:

2

Hi all, i have 2 arrays:

$foo = array(
    '1' => '2',
    '3' => array(
        '4' => '5'
    ),
    '6' => array(
        '7' => '8',
        '9' => '10',
        '11' => array(
            '12' => '13',
            '14' => '15'
        )
    )
);

$bar = array(
    '1',
    '6' => array(
        '7',
        '11' => array(
            '12'
        )
    )
);

Foo is an array i have to edit, Bar the edits i need to do.

I have to create another element in Foo array containing the elements pointed in Bar, and delete the originals from Foo.

So, with the array, the final array should be:

Array(
    '3' => array(
        '4' => '5'
    ),
    '6' => array(
        '9' => '10',
        '11' => array(
            '14' => '15'
        )
    ),
    'merged' => array(
        '1' => '2',
        '6' => array(
            '7' => '8',
            '11' => array(
                '12' => '13'
            )
        )
    )
)

I've build this recursive function, but works only for the first level of the array:

foreach($bar AS $key => $value){
    if(is_array($value)){
        s($foo, $key, $value);
    }else{
        $foo['merged'][$value] = $foo[$value];
        unset($foo[$value]);
    }
}


function s(&$form, $key, $value){
    if(is_array($value)){
        foreach($value AS $k => $v){
            s($form, $k, $v);
        }
    }else{
        $form['merged'][$value] = $form[$value];
        unset($foo[$value]);
    }
}

Any ideas?

A: 

Hey, check out THIS

(On the first comment)

Darkxes
I don't think that solves his problem exactly. That function is more of a delimiter-creating function. It assumed all sub-arrays are of the same depth (not the case here) and it generates a string as the output, not the original array with a new permutation.
steven_desu
A: 

The biggest issue with your script at the moment is that you assume an element without a key is a stand-alone construct. The array $bar actually looks like this to PHP:

$bar = array(
    '0' => '1',
    '6' => array(
        '0' => '7',
        '11' => array(
            '0' => '12'
        )
    )
)

Realizing this, when you see the key '0' in $bar it's obvious we should look at the value and move that key=>value pair to $foo['merged'], but it becomes more complicated when you see '6'. It's even more complicated when you realize you can't just nest foreach() loops since there could be potentially infinite levels to this array.

The trick to dealing with an arbitrary number of levels in any abstract data type is a recursive function with a static counter (for keeping track of level). This way we can keep going deeper into $bar, but we back out to exactly where we left out when we're done. If we make the counter an arary we can keep track of how we got to where we are. This way we can find the element within $foo later.

/* recursive_foobar is the only function you call */

function recursive_foobar(&$foo, $bar, &$merged){
    static $counter;
    if(is_empty($counter)){ // initialize counter the first time
        $counter = array();
    }
    foreach($bar as $key => $element){
        if(is_array($element)){
            $counter[] = $key;
            recursive_foobar($foo, $element, $merged[$key]);
        } else {
            $old_value = recursive_get($foo, array_push($counter, $element));
            recursive_remove($foo, array_push($counter, $element));
            array_merge($merged, $old_value);
        }
    }
    return $merged;
}

/* recursive_get returns a multi-level array containing the requested element at the lowest level */

function recursive_get($haystack, $key){
    static $return;
    if(count($key) > 1){
        $return[] = array(recursive_get($haystack[$key[0]], array_shift($key)));
    } else {
        $return[] = $haystack[$key[0]];
    }
    return $return;
}

/* recursive_remove will remove the requested element, leaving all containers untouched */

function recursive_remove(&$array, $key){
    if(count($key) > 1){
        recursive_remove($array[$key[0]], array_shift($key));
    } else {
        remove($array[$key[0]]) ???
    }
}

$foo['merged'] = array();
recursive_foobar($foo, $bar, $foo['merged']);

This is kind of sloppy, but what you requested involved some pretty high-level constructs and some complicated logic. There may be a few PHP functions I haven't memorized that could shave down a little bit of the code, but you're talking about removing arbitrary elements from arrays of arbitrary length with arbitrary depths and arbitrary number of times...

steven_desu