8

I need to merge some arrays in some different way and I use array_merge_recursive. However there is something that I need to change and I don't know how. Here is quote from php.net

If, however, the arrays have the same numeric key, the later value will not overwrite the original value, but will be appended.

I want this value, NOT to be appended, I want not to append exact values in the new array.Hope you've understood this.

Example:

$array = array(
   'some'  => array(
       'other'    => 'key',
   ),
);

$array2 = array();
$array2['some']['other'] = 'key2';

If I use array_merge_recursive It will result this:

Array (
    [some] => Array
        (
            [other] => Array
                (
                    [0] => key
                    [1] => key2
                )
        ) )

I want if it matches the same result, not to append it.Yes I know, you would say, then use array_merge, but it doesn't work well, too. If I use this:

$array = array(
   'some'  => array(
       'other'    => 'key',
   ),
);

$array2 = array();
$array2['some']['other2'] = 'key2';

print_r(array_merge($array, $array2));

It will remove $array[some][other] from the list and leave only $array[some][other2].I don't know which is better, since no one makes it better.

Alex Emilov
  • 1,243
  • 4
  • 19
  • 25
  • 1
    How deep is the nesting in your array? Just one level? – hakre Aug 07 '11 at 20:47
  • 1
    So tell us what your result should be? – scube Aug 07 '11 at 20:48
  • Well It may be unlimited.I won't use it only for 1 level. – Alex Emilov Aug 07 '11 at 20:48
  • @scube the result should be (if using array_merge) NOT to remove the prevous items from the first array. The second example shows: Array ( [some] => Array ( [other2] => key2 ) ) And I want to show: Array ( [some] => Array ( [other] => key [other2] => key2 ) ) – Alex Emilov Aug 07 '11 at 20:49
  • 1
    @Alex: What do you expect for executing that: $array = array( 'some' => array( 'other' => 'key', ), ); $array2['some']['other'] = 'key2'; when using array_merge_recursive? – scube Aug 07 '11 at 20:54
  • Well I wanted to explain that recursive doesn't fit what I need.Maybe the title confised you.Sorry. – Alex Emilov Aug 07 '11 at 21:21

5 Answers5

7

For PHP >= 5.3 just use array_replace_recursive

pinkeen
  • 690
  • 3
  • 10
  • 21
5

try this

<?php
function mymerge(&$a,$b){ //$a will be result. $a will be edited. It's to avoid a lot of copying in recursion
    foreach($b as $child=>$value){
        if(isset($a[$child])){ 
            if(is_array($a[$child]) && is_array($value)){ //merge if they are both arrays
                mymerge($a[$child],$value);
            }
            //else ignore, you can add your own logic, i.e when 1 of them is array
        }
        else
            $a[$child]=$value; //add if not exists
    }

    //return $a;
}
RiaD
  • 46,822
  • 11
  • 79
  • 123
  • This answer may not be correct probably. Because I tested your answer and results is not like what I expected. Can you please take a look at this link ? [link](https://stackoverflow.com/a/25712428) – Murat Çakmak Nov 13 '21 at 10:38
2

An other alternative, the array_merge_deep from drupal:

function array_merge_deep($arrays) {
  $result = array();
  foreach ($arrays as $array) {
    foreach ($array as $key => $value) {
      // Renumber integer keys as array_merge_recursive() does. Note that PHP
      // automatically converts array keys that are integer strings (e.g., '1')
      // to integers.
      if (is_integer($key)) {
        $result[] = $value;
      }
      // Recurse when both values are arrays.
      elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
        $result[$key] = array_merge_deep(array($result[$key], $value));
      }
      // Otherwise, use the latter value, overriding any previous value.
      else {
        $result[$key] = $value;
      }
    }
  }
  return $result;
}
darkheir
  • 8,844
  • 6
  • 45
  • 66
1

I wrote my merge class for it:

<?php

class ArrayMerge
{

    /**
     * @param array $a
     * @param array $b
     *
     * @return array
     */
    public function merge ( $a, $b ) {
        foreach ( $b as $k => $v ) {
            if ( is_array( $v ) ) {
                if ( isset( $a[ $k ] ) ) {
                    if ( $this->isDeep( $v ) ) {
                        $a[ $k ] = $this->merge( $a[ $k ], $v );
                    } else {
                        $a[ $k ] = array_merge( $a[ $k ], $v );
                    }
                } else {
                    $a[ $k ] = $v;
                }
            } else {
                $a[ $k ] = $v;
            }
        }
        return $a;
    }

    /**
     * @param array $array
     *
     * @return bool
     */
    private function isDeep ( $array ) {
        foreach ( $array as $elm ) {
            if ( is_array( $elm ) ) {
                return TRUE;
            }
        }
        return FALSE;
    }

}
palmic
  • 1,846
  • 2
  • 20
  • 30
1

I started from RiaD's version and added object handling. Need testing and feedback

function recursiveMerge(&$a,$b){ //$a will be result. $a will be edited. It's to avoid a lot of copying in recursion
        if(is_array($b) || is_object($b)){
            foreach($b as $child=>$value){
                if(is_array($a)){
                    if(isset($a[$child]))
                        recursiveMerge($a[$child],$value);
                    else
                        $a[$child]=$value;
                }
                elseif(is_object($a)){
                    if(isset($a->{$child}))
                        recursiveMerge($a->{$child},$value);
                    else
                        $a->{$child}=$value;
                }
            }
        }
        else
            $a=$b;
    }
O'Neill
  • 366
  • 2
  • 5