4

I'm sure there have been many questions like these in the past, so sorry if it's came up before. Basically, i'm trying to merge two multidimensional arrays whilst not creating 2 keys for any duplicate keys.

Here's an example:

$one = array(
    'foo' => array(
        'bar' => array(
            'hello' => 'world',
            'boom'  => 'universe'
        ),
        'whiz' => array(
            'wham' => array(
                'blam' => 'kaplow'
            )
        )
    )
);

$two = array(
    'foo' => array(
        'whiz' => 'woo',
        'king' => array(
            'kong' => 'animal'
        )
    )
);

If I was to use array_merge_recursive($one, $two); i'd get the following results:

array(1) {
  ["foo"]=>
  array(3) {
    ["bar"]=>
    array(2) {
      ["hello"]=>
      string(5) "world"
      ["boom"]=>
      string(8) "universe"
    }
    ["whiz"]=>
    array(2) {
      ["wham"]=>
      array(1) {
        ["blam"]=>
        string(6) "kaplow"
      }
      // This is the problem.
      [0]=>
      string(3) "woo"
    }
    ["king"]=>
    array(1) {
      ["kong"]=>
      string(6) "animal"
    }
  }
}

If I were to use array_merge($one, $two); i'd get the following results:

array(1) {
  ["foo"]=>
  array(2) {
    // This is good but the rest of the array is gone.
    ["whiz"]=>
    string(3) "woo"
    ["king"]=>
    array(1) {
      ["kong"]=>
      string(6) "animal"
    }
  }
}

Here's the output i'm after:

array(1) {
  ["foo"]=>
  array(3) {
    ["bar"]=>
    array(2) {
      ["hello"]=>
      string(5) "world"
      ["boom"]=>
      string(8) "universe"
    }
    // Key is replaced, rest of the array remains intact.
    ["whiz"]=>
    string(3) "woo"
    ["king"]=>
    array(1) {
      ["kong"]=>
      string(6) "animal"
    }
  }
}

So basically, i'm after the functionality of array_merge_recursive() but for it to also work like array_replace_recursive(), do you guys have any ideas?

--

I've accepted an answer for now, but don't be discouraged about showing any other possibly better methods, I will be checking back.

Thanks guys.

3
  • It'd help if you included what you actually expected as the output. The behavior of array_replace_recursive seems to be the most straight forward interpretation of the problem. Commented Jul 19, 2012 at 13:20
  • This is not recursive, but wouldn't something like $merged = $one['foo'] + $two['foo']; work? Commented Jul 19, 2012 at 13:22
  • I updated for a better example. Commented Jul 19, 2012 at 13:28

1 Answer 1

2

I think your looking for:

function farray_merge_recursive() {

    if (func_num_args() < 2) {
        trigger_error(__FUNCTION__ .' needs two or more array arguments', E_USER_WARNING);
        return;
    }
    $arrays = func_get_args();
    $merged = array();

    while ($arrays) {
        $array = array_shift($arrays);
        if (!is_array($array)) {
            trigger_error(__FUNCTION__ .' encountered a non array argument', E_USER_WARNING);
            return;
        }
        if (!$array)
            continue;
        foreach ($array as $key => $value)
            if (is_string($key))
                if (is_array($value) && array_key_exists($key, $merged) && is_array($merged[$key]))
                    $merged[$key] = call_user_func(__FUNCTION__, $merged[$key], $value);
                else
                    $merged[$key] = $value;
            else
                $merged[] = $value;
    }
    return $merged;
}

Which I think I stole from the PHP manual cos I didn't wanna write it myself.

I use it for combining and overwriting configuration arrays for my MVC framework, it works well.

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

2 Comments

This works, i'm just curious to know if there's a better solution.
@Daryl When I was looking into this in great detail that was the fastest one I found. I did make one but it's gone walkies so I just pasted this one. This function could do with optimisations but as far as I know PHP has no quick quirky way of doing this itself.

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.