$array = array (0.1 => 'a', 0.2 => 'b');
echo count ($array);
It overwrites first array element by second, just because, I used float with 0.
And hence output of above code is 1, instead of 2.
Why PHP round array index down to 0 ?
The array keys are interpreted as numeric, but numeric keys must be integers, Therefore, both float values are cast (truncated) to integer zero and 0.2 overwrites 0.1.
var_dump($array);
array(1) {
[0]=>
string(1) "b"
}
Make the array keys strings if you want to use non integer values:
$array = array ("0.1" => 'a', "0.2" => 'b');
echo count($array);
// 2
array(2) {
["0.1"]=>
string(1) "a"
["0.2"]=>
string(1) "b"
}
Only integer is allowed as key of the array.
See what we get if I print_r($array):
Array ( [0] => b )
However you can do like this:
$array = array ('0.1' => 'a', '0.2' => 'b');
Now print_r says this:
Array ( [0.1] => a [0.2] => b )
Array indices cannot be floats. They must be either integers or strings. If you would try to var_dump($array); you would see that your array looks something like this:
array(1) {
[0]=> string(1) "b"
}
You are effectively trying to set value for key 0 twice.
You cannot use floats as numeric keys. 0.1 and 0.2 both get converted to 0
Either you have to use integers or strings. Therefore, your options are:
$array = array ('0.1' => 'a', '0.2' => 'b');
Or:
$array = array (1 => 'a', 2 => 'b');
Let's see what the PHP's own excellent manual says about arrays (emphasis mine):
The key can either be an integer or a string. The value can be of any
type.
Additionally the following key casts will occur: [...] Floats are also cast to
integers, which means that the fractional part will be truncated.
So, if you look at your array:
<?php
$array = array (0.1 => 'a', 0.2 => 'b');
var_dump($array); // let's see what actually *is* in the array
echo count ($array);
you'll get this back:
array(1) {
[0]=>
string(1) "b"
}
1
So, first your array is { 0 => 'a' }, then becomes { 0 => 'b' }. The computer did exactly what you asked it to, even if not what you intended.
Possible solution: pass the array keys as strings - there is no conversion to int, and it works as expected.
$array = array ('0.1' => 'a', '0.2' => 'b');
You must use quote on non-integer keys
$array = array ('0.1' => 'a', '0.2' => 'b');
echo count($array);
You are storing 'a' into the 0.1th element and 'b' into the 0.2nd element. This is impossible. Array indexes must be integers.
Perhaps you are wanting to use associative arrays?
$array = array ('0.1' => 'a', '0.2' => 'b');
As per the php.net document on arrays for having keys:
Additionally the following key casts will occur:
Floats are also cast to integers, which means that the fractional part
will be truncated. E.g. the key 8.7 will actually be stored under 8.
i tried dumping and interpreting the result... 0.1 and 0.2 will be interpreted as 0 and the latter overwrites the former, end result is that the array key remains 0 and value is set as b.
Hence there's nothing wrong with this behavior.
its because floats are casted to integers, so the second entry overwrites the first.
Actually you are doing this:
$array = array (0 => 'a', 0 => 'b');
echo count ($array);
Php.net Array:
"Floats are also cast to integers, which means that the fractional part will be truncated. E.g. the key 8.7 will actually be stored under 8."
Related
Let me start this question with a quote on array keys from PHP Documentation
If no key is specified, the maximum of the existing integer indices is taken, and the new key will be that maximum value plus 1 (but at least 0). If no integer indices exist yet, the key will be 0 (zero).
So let's try this in the following code:
print_r(['4'=> 1, 2, 3]); // output: Array([4] => 1 [5] => 2 [6] => 3)
*Note that the first key in the array is string witch will be cast by PHP to the integer type [4]
Now lets try this in a generator function and yield the array keys one by one and see what happens
function foo() {
yield '4' => 1;
yield 2;
yield 3;
}
print_r(iterator_to_array(foo()));// output: Array([4] => 1 [0] => 2 [1] => 3)
I know generators do not behave like arrays but let's see what happens when the first key is actually an integer:
function foo() {
yield 4 => 1; // Note 4 here is an integer
yield 2;
yield 3;
}
print_r(iterator_to_array(foo())); // output: Array([4] => 1 [5] => 2 [6] => 3)
The output is as expected.
So why this is only happens when PHP cast the keys in generators? is this a normal behavior?
If in the array a key is a numerical string it will be cast by PHP to the integer type. In generators numerical string keys will not cast to integer. If you want to keep the key type, you must not use the iterator_to_array function.
function foo() {
yield '4' => 1;
yield 2;
yield 3;
}
foreach(foo() as $key => $value){
var_dump($key);
}
Output:
string(1) "4"
int(0)
int(1)
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
I am having troubles to understand how array_udiff works.
According to the documentation:
array_udiff ($array1, $array2, data_compare_func)
[...] data_compare_func function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
So considering this function:
function please_compare($a, $b) {
return $a !== $b;
};
if $a equals $b, the method will return 0, 1 otherwise (because of this).
(There is no -1 returned here and I have the feeling that the explanation comes from there but I can just compare that the values are different, not that one is greater than the other one.)
Could someone explain me array_udiff's behavior in the following snippet? I also included the output of array_diff, which is actually the behavior I was expecting?
$array1 = array('a', 'b', 'c', 'd');
$array2 = array('a', 'b', 'c');
print_r(array_udiff($array1, $array2, 'please_compare'));
/* Returns:
Array
(
[0] => a
[1] => b
[3] => d
)
*/
print_r(array_diff($array1, $array2));
/* Returns:
Array
(
[3] => d
)
*/
array_udiff relies on the comparison function returning appropriate values, because it ranks the elements of your arrays. If you add some output to your comparison function, you will see that array_udiff first determines the sort order for both arrays, and only after it has done this does it start comparing array1 elements to array2 elements. By returning 1 from your comparison function, you are telling array_udiff that 'a' > 'b' and 'b' > 'a', and similarly for all other elements in both arrays. In your particular case, this causes array_udiff to think that everything in array1 > everything in array2, until it finally happens to compare the 'c' in array1 to the 'c' in array2, and gets 0 back from your function (this is why it left 'c' out of the result). See this PHP fiddle for a demonstration of the internal working of array_udiff.
$colors = array(
'r' => 'a',
'g' => 'b',
'b' => 'c'
);
list($v, $k) = each($colors);
echo $v . " " . $k
Now the above prints r a
which I'm surprise since I thought the 'list' construct only works for numerical array. Why does it work?
Yes you are right list() only works on numerical arrays and assumes the numerical indices start at 0. but he reason why your code is working its because of each.
each traverse an array therefore converted the keys to numerical example if you run the following :
$foo = array("r"=>"a");
$bar = each($foo);
echo "<pre>";
print_r($bar);
Output
Array
(
[1] => a
[value] => a
[0] => r
[key] => r
)
You can use that array('r' => 'a'); has been converted to array(0 => 'r', 1 => 'a'); therefore you can now use list since they now have numerical keys
FROM PHP DOC
each Return the current key and value pair from an array and advance the array cursor.
each Returns the current key and value pair from the array array. This pair is returned in a four-element array, with the keys 0, 1, key, and value. Elements 0 and key contain the key name of the array element, and 1 and value contain the data.
Also
each() is typically used in conjunction with list() to traverse an array, here's an example:
Read the manual closer for each():
Returns the current key and value pair from the array array. This pair is returned in a four-element array, with the keys 0, 1, key, and value. Elements 0 and key contain the key name of the array element, and 1 and value contain the data.
So when you do each($colors), the following is returned:
array(0 => 'r' => 1 => 'a', 'key' => 'r', 'value' => 'a')
Then list() takes the values for 0 and 1 and assigns them to $v and $k respectively. Make sense?
when sort an array with letter and number, like below:
$a = array(0, 1, 'a', 'A');
sort($a);
print_r($a);
the result confuse me like that:
Array ( [0] => a [1] => 0 [2] => A [3] => 1 )
why the '0' between in 'a' and 'A'?
When you do that, the numbers are converted to a string. Number character ASCII values come between the two cases.
The strings are converted to numbers. It takes any number characters at the beginning and drops everything else to compare, unless it finds '.','E', or 'e', which can be used for floating-point conversion. If it finds no numeric characters, it evaluates to zero.