11

I have two associative array which have many content same and so I want to combine those two arrays in such a way that if I have a in array 1 and a in array 2 than in array 3 I should have entries for both a's and not 1.

I have tried using array_merge but it would overwrite entries in 1st array if there are any duplicates in 2nd array, I have also tried using + but it gives me fatal error saying Fatal error: Unsupported operand types in /home/code.php then I tried doing

(array)$ar3 = (array)$ar1 +(array)$ar2 and it seems to add up. I want to know is this the correct way to do it and also why did initially I got fatal error and than it worked as I had already defined $ar3, $ar2, $ar1 as array types.

$orders = new Order(); 
$prospectOffers = $orders->getOrder($orderConfNumber); 
$prospectOffersResult = json_decode($prospectOffers,true); 
$shoppingBasket = $cart->getCartItems(); 
var_dump($prospectOffersResult); // Both are arrays 
var_dump($shoppingBasket); //Both are arrays 
(array)$result = (array)$prospectOffersResult+(array)$shoppingBasket;

Thanks.

Gordon
  • 312,688
  • 75
  • 539
  • 559
user260204
  • 151
  • 2
  • 3
  • 9
  • See this related question http://stackoverflow.com/questions/2140090/operator-for-array-in-php/2140094#2140094 – Gordon Jan 27 '10 at 16:59
  • You are totally right to use `+`, it will union two arrays: *"The + operator appends elements of remaining keys from the right handed array to the left handed, whereas duplicated keys are **NOT** overwritten."* http://www.php.net/manual/en/language.operators.array.php Why you have to cast them as array before I don't know maybe you have weird code ;) – Felix Kling Jan 27 '10 at 17:20
  • can you add the output of the `var_dump` please. shorten them when they are very long. – Gordon Jan 27 '10 at 17:37
  • 1
    That is extremely odd, it should work without the cast. – Anthony Forloney Jan 27 '10 at 17:43
  • I am sure json_decode returns an array as am giving true in the parameter and so it returns array. Actually somehow something is being messed up in the code right now and so working on fixing it. It might take a while to post the updates. Thanks for all help. – user260204 Jan 27 '10 at 17:54
  • Update your progress as you go, so we can be on the same page when trying to assist. This question has got my eyebrow raised – Anthony Forloney Jan 27 '10 at 17:55
  • I will surely keep posted but right now the code itself is not compiling and am getting hell lot of error messages and so it might take a while for me to get back on this. – user260204 Jan 27 '10 at 18:02
  • Just tried doing it once again and now it worked as expected. So am amazed. – user260204 Jan 27 '10 at 20:33
  • congratulations, I am glad it worked for you, must have been just a glitch or your app was just running a little buggy. – Anthony Forloney Jan 27 '10 at 21:41
  • Need to figure out why did it initially gave me such buggy responses. Anyways I really appreciate all your guidance and support with this. – user260204 Jan 27 '10 at 23:46

2 Answers2

14

$array1 + $array2 will return the union of the two arrays. If they are associative, values from the left operand will be preferred if keys collide. Therefore, this is not the solution you want as values will be lost.

There is nothing wrong with the statement provided both variables are understood as arrays. Your fatal error likely occurred because one variable was actually an object, and it's possible to mistake that using var_dump. By adding the type casts you forced PHP to coerce both variables to arrays. If one variable was an object, it would have this effect:

From the PHP.net Manual

"If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible; private variables have the class name prepended to the variable name; protected variables have a '*' prepended to the variable name. These prepended values have null bytes on either side."

Now having two arrays to add, PHP had nothing to panic about. Note that while casting the two operands of + was important, it was meaningless to cast the variable you were assigning to. The expression (array)$foo does not modify $foo, but rather returns a new value. This may not be intuitive from languages that require you to declare variables, but PHP is not such a language.

On your other issue, you cannot have two of the same key in an array. This would make it impossible to index the array as the correct value to return would become ambiguous. If you wish to combine two arrays in a lossless manor, you will have to use a more complicated data structure.

My suggestion is to use an array of arrays, where:

$a1 = array('a' => 1, 'b' => 2, 'c' => 3);
$a2 = array('a' => 3, 'b' => 2, 'd' => 2);

Will become:

$a3 = array(
    'a' => array(1, 3),
    'b' => array(2, 2),
    'c' => array(3),
    'd' => array(2)
);

And the ordering is not determined. The only notable change to the structure is that all first values are arrays, allowing values of duplicate keys to be accumulated. This function does the task and might do with a better name:

// array(array) lossless_array_merge([$array1 [, $array2 [, $...]]])

function lossless_array_merge() {
  $arrays = func_get_args();
  $data = array();
  foreach ($arrays as $a) {
    foreach ($a as $k => $v) {
      $data[$k][] = $v;
    }
  }
  return $data;
}
erisco
  • 14,154
  • 2
  • 40
  • 45
  • Can you explain what this function is really doing and how does it avoid overwriting the values ? – user260204 Jan 28 '10 at 16:39
  • The function does exactly what I described with $a1, $a2, and $a3. Values from duplicate keys of the constituent arrays are accumulated in their own array rather than overwritten. To better understand how this behaves, I recommend trying the function with your own test data. – erisco Jan 29 '10 at 01:26
1

array_merge() will override duplicates only if both arrays contain the same string keys:

If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.

I believe this behavior is expected. How would you handle this case? Let's say that

$arr1 = array('a' => 1);
$arr2 = array('a' => 2);

What would be an acceptable output after the array merge?

Anax
  • 9,122
  • 5
  • 34
  • 68