php array_merge associative arrays
Asked Answered
C

7

27

I'm trying to prepend an item to the beginning of an associative array. I figured the best way to do this is to use array_merge, but I'm having some odd consequences. I get the id and Name of products from a mysql database, and it gets returned as an associative array, like this (not the actual data coming back, but sample data for this question that represents what the data looks like approximately):

$products = array (1 => 'Product 1', 42 => 'Product 42', 100 => 'Product 100');

this is getting sent to an html helper to create a dropdown that associates the key with the value, and the value of the array item gets set as the text in the drop down select control. I need the first item to be something like "Please Select" with a key of 0, so I did this:

$products = array_merge(array(0 => "Select a product" ), $products);

The resulting array looks like this:

array(
  0 => 'Select a product', 
  1 => 'Product 1', 
  2 => 'Product 42', 
  3 => 'Product 100' 
);

when What I really wanted was not to lose the keys of the associative array. I was told that you can properly use array_merge with associative arrays in the manner I tried, however, I believe because my keys are ints that it is not treating the array as a true associative array, and compressing them as illustrated above.

The question is: Why is the array_merge function changing the keys of the items? can I keep it from doing this? OR is there another way for me to accomplish what I'm trying to do, to add the new item at the beginning of the array?

Carbonous answered 8/3, 2011 at 14:21 Comment(1)
I've had the exact same problem with array_merge(). I'm not sure if it's a bug or we are trying to use it in a way that was unintended. Solution, just run through a quick foreach loop and rebuild your array. Start with $myarray = array(0 => 'Select a product');Tupiguarani
M
58

From the docs:

If you want to append array elements from the second array to the first array while not overwriting the elements from the first array and not re-indexing, use the + array union operator

The keys from the first array argument are preserved when using the + union operator, so reversing the order of your arguments and using the union operator should do what you need:

$products = $products + array(0 => "Select a product");
Missus answered 8/3, 2011 at 14:22 Comment(3)
But wouldn't this append the "Select a product" to the end of the array?Krouse
@Bob: it's a merge, not an append; either way the union operator preserves keys, so as long as there isn't a key 0 in $products already then there will be after the union.Missus
i'm trying $products = array(0 => "Select a product") + $products; Testing... It worked, thanks. There are so many different methods and ways to manipulate arrrays, it gets confusing.Carbonous
P
6

Just for the fun of it

$newArray = array_combine(array_merge(array_keys($array1),
                                      array_keys($array2)
                                     ),
                          array_merge(array_values($array1),
                                      array_values($array2)
                                     )
                         );
Polynesian answered 8/3, 2011 at 14:31 Comment(0)
F
4

array_merge will recalculate numeric indexes. Because your associative array iuses numeric indexes they will get renumbered. You either insert a non-numeric charadter in front of the indices like:

$products = array ('_1' => 'Product 1', '_42' => 'Product 42', '_100' => 'Product 100');

Or you can create the resulting array manually:

$newproducts = array (0 => "Select a product");
foreach ($products as $key => $value)
    $newproducts[$key] = $value;
Forworn answered 8/3, 2011 at 14:33 Comment(1)
I figured that much out, one of the things i tried was to convert the keys to strings, so instead of 1 i would use '1', but it still treated it like a numeric int, the weakness of the types of php is something I need to get used to coming from a C background, with more strong typing.Carbonous
K
2

You could use array operator: +

$products = array(0 => "Select a product" ) + $products;

it will do a union and only works when the keys don't overlap.

Krouse answered 8/3, 2011 at 14:27 Comment(1)
yep, that was the solution, but someone else posted it first. but i still upvoted it, I didn't know the + operator could be used like that, thank you for the answer none-the-lessCarbonous
B
1

From the docs:

Values in the input array with numeric keys will be renumbered with incrementing keys starting from zero in the result array.

Bomarc answered 8/3, 2011 at 14:24 Comment(0)
T
1

You man want to look at array_replace function.

In this example they are function the same:

$products1 = array (1 => 'Product 1', 42 => 'Product 42', 100 => 'Product 100');
$products2 = array (0 => 'Select a product');

$result1 = array_replace($products1, $products2);
$result2 = $products1 + $products2;

Result for both result1 and result2: Keys are preserved:
array(4) {
  [1] => string(9) "Product 1"
  [42] => string(10) "Product 42"
  [100] => string(11) "Product 100"
  [0] => string(16) "Select a product"
}

However they differ if the same key is present in both arrays: + operator does not overwrite the value, array_replace does.

Ticker answered 6/3, 2015 at 10:28 Comment(1)
Perfect. This should be accepted answer since accepted one cant solve duplicate keys.Trinomial
L
0

You could try something like

$products[0]='Select a Product'
ksort($products);

That should put the 0 at the start of the array but it will also sort the other products in numeric order which you may not want.

Lyse answered 8/3, 2011 at 14:39 Comment(1)
yes, the clients wanted it in some messed up arbitrary order, the <select> options were hard coded in the original application, so when they added new products, the previous developer had to add them to the <options> which I absolutely refused to do such a horrible anti-patern, so I just added a sort order to the product edit screen.Carbonous

© 2022 - 2024 — McMap. All rights reserved.