What's the difference between array_merge and array + array? [duplicate] - php

This question already has answers here:
Merging two arrays with the "+" (array union operator) How does it work?
(9 answers)
Closed last year.
A fairly simple question. What's the difference between:
$merged = array_merge($array1, $array2);
and
$merged = $array1 + $array2;
?

Here's a simple illustrative test:
$ar1 = [
0 => '1-0',
'a' => '1-a',
'b' => '1-b'
];
$ar2 = [
0 => '2-0',
1 => '2-1',
'b' => '2-b',
'c' => '2-c'
];
print_r($ar1+$ar2);
print_r(array_merge($ar1,$ar2));
with the result:
Array
(
[0] => 1-0
[a] => 1-a
[b] => 1-b
[1] => 2-1
[c] => 2-c
)
Array
(
[0] => 1-0
[a] => 1-a
[b] => 2-b
[1] => 2-0
[2] => 2-1
[c] => 2-c
)
Notice that duplicate non-numeric keys will take the first value using the union operator but the later one using the array_merge.
For numeric keys, the first value will be used with the union operator whereas the all the values will be used with the array_merge, just reindexed.
I generally use union operator for associative arrays and array_merge for numeric. Of course, you can just as well use the array_merge for associative, just that the later values overwrite earlier ones.

The difference is:
The + operator takes the union of the two arrays, whereas the array_merge function takes the union BUT the duplicate keys are overwritten.

Source: https://softonsofa.com/php-array_merge-vs-array_replace-vs-plus-aka-union/
Stop using array_merge($defaults, $options):
function foo(array $options)
{
$options += ['foo' => 'bar'];
// ...
}
Note: array_replace function exists since PHP5.3.

array_merge() causes all numeric keys found in the input arrays to be reindexed in the resultant array. The union operator + does not cause a reindex.

The + sign only takes the value from the first occurence of an array key.
array_merge takes the value from the last occurrence of an array key.
Example:
$first = ['a'=>'one',
'b'=>'two',
'c'=>'three'];
$second = ['a'=>'fourth',
'b'=>'fifth',
'c'=>'sixth',
'3'=>'number three'];
$merged = $first + $second;
echo "<pre> plus sign merge\n";
var_dump($merged);
$merged = array_merge($first,$second);
echo "\n array_merge function merge\n";
var_dump($merged);
This outputs:
plus sign merge
array(4) {
["a"]=>
string(3) "one"
["b"]=>
string(3) "two"
["c"]=>
string(5) "three"
[3]=>
string(12) "number three"
}
array_merge function merge
array(4) {
["a"]=>
string(6) "fourth"
["b"]=>
string(5) "fifth"
["c"]=>
string(5) "sixth"
[0]=>
string(12) "number three"
}
Interesting to note in this is that the array_merge actally erases the '3' index of number three even though it's a string, because it's a number.
So take care when merging with array_merge arrays with numerical indexes. They might lose their keys. if they are important to you precede them with a string.
Instead of '3' => 'three' use something like '_3' => 'three'
Also if you use numerical indexes it's important to note that if you add two array, it only looks at the numerical index and takes the value from the "first" array that has an array key with that value.
Array merge will merge the arrays together, ignoring similar keys and values.
So depending on the "type" of array indexes, numerical or string, the results will vary.
$arr = ['foo', 'bar', 'baz'];
$arr2 = ['xfoo', 'xbar', 'baz'];
$arr3 = $arr2 + $arr;
$arr4 = array_merge($arr, $arr2);
var_dump($arr3);
which gives the output:
array(3) {
[0]=>
string(4) "xfoo"
[1]=>
string(4) "xbar"
[2]=>
string(3) "baz"
}
array(6) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
[2]=>
string(3) "baz"
[3]=>
string(4) "xfoo"
[4]=>
string(4) "xbar"
[5]=>
string(3) "baz"
}
var_dump($arr4);

I believe array_merge overwrites duplicate non_numeric keys while $array1 + $array2 does not.

Yet another example (arrays without explicit keys; it's obvious regarding to how the operator + and array_merge work, but "obvious" things are simpler when seen ;))
$a = array('apple');
$b = array('orange', 'lemon');
echo '$a + $b = '; print_r($a + $b);
echo 'array_merge($a, $b) = '; print_r(array_merge($a, $b));
will give:
$a + $b = Array
(
[0] => apple
[1] => lemon
)
array_merge($a, $b) = Array
(
[0] => apple
[1] => orange
[2] => lemon
)

Please pay attention for another difference: the union (+) won't overwrite non-empty value with empty value (considering a same key), whereas array_merge will:
$a = array('foo' => 'bar');
$b = array('foo' => ''); // or false or 0
print_r($a+$b);
print_r(array_merge($a, $b);
Outputs :
Array
(
[foo] => bar
)
Array
(
[foo] => 0
)

So apparently if you change the order both union and merge will do the same thing
$a = array('foo' => 'bar', 'x' => 'fromA');
$b = array('foo' => null, 'x' => 'fromB');
echo '$a+$b: ';
var_dump($a+$b);
echo '$b+$a: ';
var_dump($b+$a);
echo 'array_merge($a, $b): ';
var_dump(array_merge($a, $b));
echo 'array_merge($b, $a): ';
var_dump(array_merge($b, $a));
Outputs :
$a+$b: array(2) {
["foo"]=>
string(3) "bar"
["x"]=>
string(5) "fromA"
}
$b+$a: array(2) {
["foo"]=>
NULL
["x"]=>
string(5) "fromB"
}
array_merge($a, $b): array(2) {
["foo"]=>
NULL
["x"]=>
string(5) "fromB"
}
array_merge($b, $a): array(2) {
["foo"]=>
string(3) "bar"
["x"]=>
string(5) "fromA"
}
Keep in mind the order of the arrays.

Related

How to fill a empty value in KEY=> VALUE for array_combine in php

I wish to make Key and Value combining with 2 arrays, but both arrays are not equal.
$array1 = array("1","2","3","4","5");
$array2 = array("apple","banana","","dog","");
$key_value = array_combine($array1,$array2);
The output is:
array_combine(): Both parameters should have an equal number of elements
But I need to below output be like
print_r($key_value);
array(5) {
[1]=> string(5) "apple"
[2]=> string(6) "banana"
[3]=> string(8) "No Value"
[4]=> string(3) "dog"
[5]=> string(8) "No Value"
}
How can do this if null, insert "no value" text.
You can do it via foreach loop:
$res = [];
foreach($array1 as $ind=>$num){
$res[$num] = $array2[$ind] === "" ? "No Value" : $array2[$ind];
}
print_r($res);
Output:
Array
(
[1] => apple
[2] => banana
[3] => No Value
[4] => dog
[5] => No Value
)
Demo
use array_map() and array_combine()
<?php
$array1 = array("1","2","3","4","5");
$array2 = array("apple","banana","","dog","");
$array2 = array_map(function($v){
return (empty($v)) ? "No Value" : $v;
},$array2);
$key_value = array_combine($array1,$array2);
print_r($key_value);
https://3v4l.org/CY4ku

Getting value of nested array's which exist in every array

I have the following (nested) array:
array(3) { [16]=> array(3) { [0]=> int(159) [1]=> int(160) [2]=> int(158) }
[21]=> array(2) { [0]=> int(160) [1]=> int(158) }
[19]=> array(2) { [0]=> int(158) [1]=> int(159) } }
As you can see it contains 3 child array's. The child array's all contain the integer '158' as an value but also '159'. I want to somehow loop trough the child array's and do a check if all child array's contain that value. Then I want to return an array with only these values.
I know i could use array_intersect for this however the nested array's are generated dynamically so i'm not sure how to deal with this using array intersect:
<?php
$arr1 = array('158','250','342');
$arr2 = array('158','142','352');
$diff1 = array_intersect($arr1, $arr2);
print_r( $diff1 );
//RETURNS Array ( [0] => 158 )
?>
You can use the splat operator(...) to pass all the subarrays into array_intersect() in one go...
$arr1 = [['158','250','342'],['158','142','352'],['1421','158','3521']];
$diff1 = array_intersect(...$arr1);
print_r( $diff1 );
//RETURNS Array ( [0] => 158 )
After a bit searching around I found the following:
$result = call_user_func_array('array_intersect', $productStoreArray);
As seen on: php dynamic array_intersect
This solves my problem because it returns to me:
//RETURNS Array ( [0] => 158, 1 => 159 )

Sort array based on the numbers and a certain piece of text that occurs within a string

I have an array which I got from a directory with pdf files in it using scandir
$array = array(7) {
[0]=> string(17) "q150824-spost.pdf"
[1]=> string(17) "s150826-spost.pdf"
[2]=> string(16) "s150826-spro.pdf"
[3]=> string(17) "t150827-spost.pdf"
[4]=> string(16) "t150827-spro.pdf"
[5]=> string(17) "v150825-spost.pdf"
[6]=> string(16) "v150825-spro.pdf"
}
I need to sort the array by the numbers in the file name (eg. 150824 which is actually a date) which I can do using the following:
usort($array, function($a, $b) {
return filter_var($a, FILTER_SANITIZE_NUMBER_INT) - filter_var($b, FILTER_SANITIZE_NUMBER_INT);
});
The above gives me an array sorted by the numbers (which is almost what I want):
$array = array(7) {
[0]=> string(17) "q150824-spost.pdf"
[1]=> string(17) "v150825-spost.pdf"
[2]=> string(16) "v150825-spro.pdf"
[3]=> string(16) "s150826-spro.pdf"
[4]=> string(17) "s150826-spost.pdf"
[5]=> string(17) "t150827-spost.pdf"
[6]=> string(16) "t150827-spro.pdf"
}
However, in addition to this I would also like to sort alphabetically by spost and spro (the text before .pdf) I'm at a loss as to how to achieve this though?
If two strings in the array have the same numbers/date (eg. 150826) I want to then sort by spost first and then spro.
This should work for you:
First just grab the number and the topic name out of the file name with preg_match_all() and assign it to the variables. After this simply sort it by the topic, if the numbers are equal, otherwise by the numbers.
<?php
usort($arr, function($a, $b){
preg_match_all("/^\w(\d+)-(\w+)/", $a, $mA);
preg_match_all("/^\w(\d+)-(\w+)/", $b, $mB);
$numberA = $mA[1][0];
$numberB = $mB[1][0];
$topicA = $mA[2][0];
$topicB = $mB[2][0];
if($numberA == $numberB){
return strcmp($topicA, $topicB);
}
return $numberA > $numberB ? 1 : -1;
});
print_r($arr);
?>
output:
Array
(
[0] => q150824-spost.pdf
[1] => v150825-spost.pdf
[2] => v150825-spro.pdf
[3] => s150826-spost.pdf
[4] => s150826-spro.pdf
[5] => t150827-spost.pdf
[6] => t150827-spro.pdf
)
Actually you can just do the following
$array =[
"q150824-spost.pdf",
"s150826-spost.pdf",
"s150826-spro.pdf",
"t150827-spost.pdf",
"t150827-spro.pdf",
"v150825-spost.pdf",
"v150825-spro.pdf",
];
usort($array, function($a, $b) {
return filter_var($a, FILTER_SANITIZE_NUMBER_INT) - filter_var($b, FILTER_SANITIZE_NUMBER_INT) + (strlen($b) > strlen($a) ? 1 : 0);
});
print_r($array);
Output
Array
(
[0] => q150824-spost.pdf
[1] => v150825-spost.pdf
[2] => v150825-spro.pdf
[3] => s150826-spost.pdf
[4] => s150826-spro.pdf
[5] => t150827-spost.pdf
[6] => t150827-spro.pdf
)
It is sort by spost first and then spro

Push columnar values of multiple arrays (of different lengths) to form a flat array

I have from 3 to 10 arrays containing 20 to 50 value each.
I want to merge them into a single, flat, indexed array, but not the way array_merge works.
I rather want to take the 1st value of the 1st array, then the 1st value of the second array, then the 1st value of the third array and so on.
Keys are not an issue here, It could be numerical or associative array, I'm just keeping the values, not the original keys.
Values in real application can be mixed so merging and sorting afterwards is not an option.
So if I had 3 arrays like so:
$array1 = array('1-1', '1-2', '1-3');
$array2 = array('2-1', '2-2', '2-3', '2-4');
$array3 = array('3-1', '3-2');
I would need the result to be an array containing the value in this order:
1-1, 2-1, 3-1, 1-2, 2-2, 3-2, 1-3, 2-3, 2-4
So far I have this piece of code :
$array = array($array1, $array2, $array3);
$newarray = array();
foreach ($array as $a) {
$v = array_shift($a);
if (isset($v)) {
$newarray[] = $v;
}
}
print_r($newarray);
but, of course, it only runs the 1st set of value and give me:
Array ( [0] => 1-1 [1] => 2-1 [2] => 3-1 )
array_shift is what I need here because it remove the value from the old array (I don't need it anymore) and I move it to the new array (if it isset). see: http://php.net/manual/en/function.array-shift.php
I'm pretty sure I will need a function and loop it until all arrays are empty, but I just can't wrap my head around this one. Any help will be greatly appreciated. Or even better if someone knows a native php function that does that.
Here's a simple one-liner...
$arr1 = ['1-1', '1-2', '1-3'];
$arr2 = ['2-1', '2-2', '2-3', '2-4'];
$arr3 = ['3-1', '3-2'];
$result = array_filter(call_user_func_array(array_merge, array_map(null, $arr1, $arr2, $arr3)));
So, maybe not so simple... Some explanation.
array_map(null, ...); makes use of the feature of array_map explained in example 4 of the PHP docs but without any transformation to the values (hence, null).
So, this will give you:
array(4) {
[0]=>
array(3) {
[0]=>
string(3) "1-1"
[1]=>
string(3) "2-1"
[2]=>
string(3) "3-1"
}
[1]=>
array(3) {
[0]=>
string(3) "1-2"
[1]=>
string(3) "2-2"
[2]=>
string(3) "3-2"
}
[2]=>
array(3) {
[0]=>
string(3) "1-3"
[1]=>
string(3) "2-3"
[2]=>
NULL
}
[3]=>
array(3) {
[0]=>
NULL
[1]=>
string(3) "2-4"
[2]=>
NULL
}
}
Then, we need to "flatten" the array, concatenating all the sub-arrays together.
This is achieved using array_merge, but that doesn't take an array, so we use call_user_func_array to feed the array into it's arguments.
Then the array_filter to remove the nulls (introduced by array_map due to the original arguments not being the same length).
Just added for reference, if you're running PHP 5.6+ you can take advantage of the new ... operator to signify n number of arguments in a function declaration and/or call. Implementation would be something like this (reference):
function merge_vertical(...$arrays) {
return array_filter(array_merge(...array_map(null, ...$arrays)));
}
print_r(merge_vertical($array1, $array2, $array3));
Output:
Array
(
[0] => 1-1
[1] => 2-1
[2] => 3-1
[3] => 1-2
[4] => 2-2
[5] => 3-2
[6] => 1-3
[7] => 2-3
[10] => 2-4
)
Try this code
$array1=array('1-1','1-2','1-3');
$array2=array('2-1','2-2','2-3','2-4');
$array3=array('3-1','3-2');
$array=array($array1,$array2,$array3);
$array2 = $array ;
function cmp($a, $b){
return (count($b) - count($a));
}
usort($array2, 'cmp');
$xax_length = count($array2[0]);
$newarray=array();
for($i=0;$i<$xax_length;$i++) {
foreach($array as &$a){
$v=array_shift($a);
if(isset($v)){
$newarray[]=$v;
}
}
}
print_r($newarray);
I would recommend hashing through all of the arrays in a for loop.
$array1=array('1-1','1-2','1-3');
$array2=array('2-1','2-2','2-3','2-4','2-5');
$array3=array('3-1','3-2');
$maxSize=max(count($array1),count($array2),count($array3));
$array=array($array1,$array2,$array3);
$newarray=array();
for ($i = 0; $i < $maxSize; $i++) {
for ($x = 0; $x < count($array); $x++) {
if(count($array[$x]) > $i){
$newarray[] = $array[$x][$i];
}
}
}
print_r($newarray);
While it is sexy to use array_map() to transpose array data so that columns of data can be easily extracted, the problem is that when processing data structures which are not perfectly shaped matrices, you will have null values generated.
Other answers fix the null population by calling array_filter() to mop up all of the unwanted nulls, but this will do harm to your result if you have false, null or zero-ish values in your data set that you actually wish to keep.
Also, this question states that key may be numeric or associative. This is another reason why transposing with array_map() is less attractive -- because it will choke on arrays with non-numeric keys.
While less elegant and sexy than some earlier posted answers, this answer wins out in terms of reliability because it will never destroy falsey values.
Add all arrays into a parent array (container), then iterate those arrays one at a time. "Shift" the first element off of each array and push it into the result array. If an array has no more elements, then unset() it so that it no longer occurs as a child of the parent array. (The original array variable will not be destroyed; only its copied version which exists inside the container.)
When the parent array has no more children, then stop looping.
Code: (Demo)
$array1 = [2 => 0, 0 => 1, 1 => '2'];
$array2 = [false, true, 'false' => false, 'true' => true];
$array3 = [null, 'null'];
$all = [$array1, $array2, $array3];
$result = [];
while ($all) {
foreach ($all as $index => &$array) {
$result[] = array_shift($array);
if (!$array) {
unset($all[$index]);
}
}
}
var_export($result);
Output:
array (
0 => 0,
1 => false,
2 => NULL,
3 => 1,
4 => true,
5 => 'null',
6 => '2',
7 => false,
8 => true,
)
You can use the + operator.
$c = $a + $b
Good luck !

Merging two arrays without changing key values php

I have two arrays in php as shown in the code
<?php
$a=array('0'=>array('500'=>'1','502'=>'2'));
$b=array('0'=>array('503'=>'3','504'=>'5'));
print_r(array_merge($a[0],$b[0]));
?>
I need to merge two arrays. array_merge function successfully merged two of them but key value gets changed. I need the following output
Array
(
[0]=>Array(
[500] => 1
[502] => 2
[503] => 3
[504] => 5
)
)
What function can I use in php so that the following output is obtained without changing key values?
From the documentation, Example #3:
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:
<?php
$array1 = array(0 => 'zero_a', 2 => 'two_a', 3 => 'three_a');
$array2 = array(1 => 'one_b', 3 => 'three_b', 4 => 'four_b');
$result = $array1 + $array2;
var_dump($result);
?>
The keys from the first array will be preserved. If an array key exists in both arrays, then the element from the first array will be used and the matching key's element from the second array will be ignored.
array(5) {
[0]=>
string(6) "zero_a"
[2]=>
string(5) "two_a"
[3]=>
string(7) "three_a"
[1]=>
string(5) "one_b"
[4]=>
string(6) "four_b"
}
Therefore, try: $a[0] + $b[0]
$a=array('0'=>array('500'=>'1','502'=>'2'));
$b=array('0'=>array('503'=>'3','504'=>'5'));
$c = $a + $b; //$c will be a merged array
see the answer for this question
Try:
$final = array();
$a=array('0'=>array('500'=>'1','502'=>'2'));
$b=array('0'=>array('503'=>'3','504'=>'5'));
foreach( $a as $key=>$each ){
$final[$key] = $each;
}
foreach( $b as $key=>$each ){
$final[$key] = $each;
}
print_r( $final );
$a=array('0'=>array('500'=>'1','502'=>'2'));
$b=array('0'=>array('503'=>'3','504'=>'5'));
$c = $a[0] + $b[0];
print_r($c);
Will print:
Array ( [500] => 1 [502] => 2 [503] => 3 [504] => 5 )
Just write :
<?php
$a = array(2=>'green', 4=>'red', 7=>'yellow',3=>'Green');
$b = array(8=>'avocado');
$d = $a+$b;
echo'<pre>'; print_r($d);
?>
out put :
Array
(
[2] => green
[4] => red
[7] => yellow
[3] => Green
[8] => avocado
)

Categories