Why PHP treating "1" as integer in array_merge()
ex.
$arr1 = array( "1"=>1, 2 , 3 );
$arr2 = array( "1"=>1, 2 );
print_r(array_merge( $arr1 , $arr2 ));
var_dump("1");
var_dump(1);
Outputs:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 1
[4] => 2
)
string(1) "1" int(1)
As per array_merge() function :-
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.
This is not array_merge() related, but rather on how array keys are handled by PHP. See http://php.net/manual/en/language.types.array.php for implicit cast of keys.
You simply shouldn't use numeric values as string keys because they are treated as numerical keys.
The most important thing in this case is:
Strings containing valid integers will be cast to the integer type.
E.g. the key "8" will actually be stored under 8. On the other hand
"08" will not be cast, as it isn't a valid decimal integer.
This above is related to PHP arrays as in PHP Arrays manual
You can see it using this sample code:
$arr1 = array( "1"=>1, "01" => 4, 2 , 3 );
var_dump($arr1);
It will return:
array(4) { 1=> int(1) ["01"]=> int(4) [2]=> int(2) [3]=> int(3) }
So your key "1" became numerical key but key "01" is still string key
Related
I am simply trying to turn this:
Array
(
[0] => 20200330
[1] => 20200329
[2] => 20200328
)
Into this and I am having an extremely hard time
Array
(
20200330,
0200329,
20200328,
)
All arrays in PHP have a unique key for each value within that array.
By default they are 0, 1, 2, 3, etc unless you explicitly set them (e.g. $a = ['key' => 1234];).
It is possible to "remove" keys (set to default without impacting the order) through the use of the array_values() function:
$a = ['a' => 123, 'b' => 321];
$a = array_values($a);
print_r($a); // [0 => 123, 1 => 321]
But it is not possible to entirely remove the keys from an array.
Arrays are by default associated with numbers starting from 0
<?php
$arr=array("String1","String2","Something else");
var_dump($arr);
?>
Output will be:
array(3) {
[0]=>
string(7) "String1"
[1]=>
string(7) "String2"
[2]=>
string(14) "Something else"
}
So if you want to access element of array you type $arr[index] and index is number by default
first array
[0]=> Brian
[1]=> A
[2]=> Leo
[3]=> A
[4]=> Mike
second array
[0]=> 1
[1]=> 2
[2]=> 3
[3]=> 4
[4]=> 5
I want to check if in first array there are duplicates, if yes, save only the first occurrence of that value, the other removes, remember those keys, and delete them from the second array too. In the end i want to have
first array
[0]=> Brian
[1]=> A
[2]=> Leo
[3]=> Mike
second array
[0]=> 1
[1]=> 2
[2]=> 3
[3]=> 5
I tried with this but second array does not have duplicates so it won't work for both array:
array_values(array_unique($array));
You did
array_values(array_unique($array));
This will give unique values of $array, but you won't find which index of second array needs to be unset.
Approach #1:
Your best shot is a simple for loop with an isset check. If we find the value already present in our $set(a new temp array), we unset that index from both original arrays, else we preserve it.
Snippet:
<?php
$arr1 = [
'Brian',
'A',
'Leo',
'A',
'Mike'
];
$arr2 = [
1,2,3,4,5
];
$set = [];
foreach($arr1 as $key => $value){
if(!isset($set[$value])) $set[$value] = true;
else{
unset($arr1[$key]); // foreach creates a copy of $arr1, so safe to unset
unset($arr2[$key]);
}
}
print_r($arr1);
print_r($arr2);
Demo: https://3v4l.org/BQ9mA
Approach #2:
If you don't like for loops, you can use array wrappers to do this. You can use array_combine to make first array values as keys and second array values as arrays. Note that this would only preserve the latest key value pairs, so we do a array_reverse to only maintain first occurrence pairs.
Snippet:
<?php
$arr1 = [
'Brian',
'A',
'Leo',
'A',
'Mike'
];
$arr2 = [
1,2,3,4,5
];
$filtered_data = array_combine(array_reverse($arr1),array_reverse($arr2));
print_r(array_keys($filtered_data));
print_r(array_values($filtered_data));
Demo: https://3v4l.org/mlstg
This simply builds a temp array using the values from your 2 arrays.
Because we use values of $a1 as the key, dups get overwritten and therefore lost. The array_keys_exists() check makes sure the first Dup is used and not subsequent dups. Then we just split the array into the two input arrays.
$a1 = ['Brian', 'A', 'Leo', 'A', 'Mike'];
$a2 = [1,2,3,4,5];
#temp array created using values of $a1 as key so dups get dropped because they are reused
foreach ($a1 as $i=>$a) {
if ( ! array_key_exists($a, $new)){
$new[$a] = $a2[$i];
}
}
$a1 = array_keys($new);
$a2 = array_values($new);
print_r($a1);
print_r($a2);
RESULT:
Array
(
[0] => Brian
[1] => A
[2] => Leo
[3] => Mike
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
)
Please note that array_unique preserves keys so you can easily use it to filter the second array too:
$firstArray = array_unique($firstArray);
$secondArray = array_intersect_key($secondArray, $firstArray);
var_dump(array_values($firstArray), array_values($secondArray));
From the docs of array_unique:
Note that keys are preserved. If multiple elements compare equal under the given sort_flags, then the key and value of the first equal element will be retained.
I have an array:
$a = array('color' => 'green', 'format' => 'text', 'link_url');
and another:
$b = array('zero', 'one', 'two', 'three', 'test' => 'ok', 'four');
And with array_merge() I have an array like this:
Array
(
[color] => green
[format] => text
[0] => link_url
[1] => zero
[2] => one
[3] => two
[4] => three
[test] => ok
[5] => four
)
Why PHP sets array key as above? Why not like this:
Array
(
[color] => green
[format] => text
[2] => link_url
[3] => zero
[4] => one
[5] => two
[6] => three
[test] => ok
[8] => four
)
That's because numeric IDs are counted separately from seeing indices. The string indices have no number and are not counted.
Quoting from the PHP manual for your original array definitions:
The key is optional. If it is not specified, PHP will use the increment of the largest previously used integer key.
and from the docs on array_merge():
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.
Values in the input array with numeric keys will be renumbered with incrementing keys starting from zero in the result array.
So it's all quite explicitly documented
Well, if you look at the original array, should be clear:
array(3) {
["color"]=>
string(5) "green"
["format"]=>
string(4) "text"
[0]=>
string(8) "link_url"
}
You appear to have assumed an ordering or a congruity with non-numeric keys, which does not exist.
The numeric keys have an order and this is represented in their new values; the string keys are not part of that ordering system and thus do not affect those new numeric values.
This is simply the way it is and it makes complete sense.
Please check the doc :
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.
Values in the input array with numeric keys will be renumbered with incrementing keys starting from zero in the result array.
Ref: http://www.php.net/manual/en/function.array-merge.php
echo count(array("1" => "A", 1 => "B", "C", 2 => "D"));
This outputs 2. I've played around with it and noticed that PHP identifies both string numbers and integers the same when used as keys in an array. Seems like integers are prioritized. Also when I var_dump the array only elements containing the value "B" and "D" are displayed. I understand why "A" is not displayed but why is "C" not in the var_dump?
Your array is basically being built as follows:
Key "1" is an integer-like string, treat as integer 1
Assign "A" to key 1
Assign "B" to key 1 (overwrite "A")
No explicit key, take greatest key so far and add 1 = 2
Assign "C" to key 2
Assign "D" to key 2 (overwrite "C")
Thus your resulting array is array(1=>"B",2=>"D");
It appears as though you cannot mix associative arrays and non-associative arrays together. If you add an index to C like you did for everything else, it works as expected. As for strings, if they are a valid integer then it will be casted to an int arrays.
$arr = array("0" => "A", 1 => "B", 2 => "C", 3 => "D");
// However, if you do:
$array = array(
"0" => "A",
1 => "B",
"2" => array(1, 2, 3)
);
It shows up like you would expect in a var_dump array(3) { [0]=> string(1) "A" [1]=> string(1) "B" [2]=> array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } }
I've two arrays array1 and array2 and I want to add all elements of array2 to the end of array1. array1 contains many items.
The keys are numeric and I don't want this syntax:
array1 = array1 + array2
or
array1 = SomeArrayFun(array1,array2)
As it takes away CPU times ( as array is created twice )
What I want is:
array1 . SomeAddFun(array2); // This will not create any new arrays
Is there any way to do it?
If you'd like to append data to an existing array you should se array_splice.
With the proper arguments you'll be able to insert/append the contents of $array2 into $array1, as in the below example.
$array1 = array (1,2,3);
$array2 = array (4,5,6);
array_splice ($array1, count ($array1), 0, $array2);
print_r ($array1);
output:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
)
You might use ArrayObject with the append function:
$arrayobj = new ArrayObject(array('first','second','third'));
$arrayobj->append('fourth');
Result:
object(ArrayObject)#1 (5) {
[0]=>
string(5) "first"
[1]=>
string(6) "second"
[2]=>
string(5) "third"
[3]=>
string(6) "fourth"
}
Don't know for appending arrays though, as they seem to be appended as a "subarray" and not as part of the whole.
Docs: http://www.php.net/manual/en/arrayobject.append.php