I have this array
$array = array(2, 1, "img1", "img2", "img10", 1.5, "3.14", "2.72");
after applying sort
function it becomes
sort($array);
Array
(
[0] => 2.72
[1] => 3.14
[2] => img1
[3] => img10
[4] => img2
[5] => 1
[6] => 1.5
[7] => 2
)
I did't understand how the sorting is performed.
Can anyone explain how the output array is achieved?
EDIT:
Here the question is not that which SORT FLAG
should I use but the question is how the above sorting is performed. Any advise to use another SORT FLAG
is useless here.
The first two numbers were actual strings (you passed them within quotes), so they are treated like so: numbers come before any letter in alphabetic sorting.
The other ones were real numbers (without quotes), so the function put them separately, sorting them numerically.
array(8)
0 => '2.72' [alphabetical]
1 => '3.14' [alphabetical]
2 => 'img1' [alphabetical]
3 => 'img10' [alphabetical]
4 => 'img2' [alphabetical]
5 => 1 [numeric]
6 => 1.5 [numeric]
7 => 2 [numeric]
So, the function has to decide if it will sort the elements alphabetically (a,b,c...) or numerically (1,2,3..) so it just checks the variable type.
Like Pekka pointed out, there are flags that can be set to force the type of sorting. They are described in the docs.
This theory was proved wrong in the comments and I'm totally lost now (:
This comment at the docs contains some interesting points on this issue.
Using the information in the link for Coanda as a starting point, it is clear that PHP using type juggling when comparing objects of different types. The problem is understanding what is getting casted to what during comparison, and I still havn't been able to find a complete list, but in general:
string compared to int will turn into
(int) string <,>,=, (int) int
In this case the string, after casting becomes 0, so all ints are greater than a string. (expected). This is the only case we need to worry about for this sort.
PHP uses quicksort, and most likely chooses its pivot point as array[n/2]
where n is the number elements in the array. Knowing these two pieces of information we quicksort the above array:
$pivot = $array[n/2] //n is the number of elements, this sets $pivot='img2'
//compare each element in the list (i am going to this by hand for demonstration)
(int) 'img2' < 2 //int to int comparison;'img2' resolves to 0 and 0 < 2
(int) 'img2' < 1 //int to int comparison;'img2' resolves to 0 and 0 < 1
'img2' > 'img1' // string to string comparison; strcmp is +256
'img2' > 'img 10' //string to string comparison; strcmp is +256
(float) 'img2' < 1.5 //float to float comparison;'img2' resolves to 0 and 0<1.5
'img2' > '3.14' //string to string comparison; strcmp is +54
'img2' > '2.72' //string to string comparison; strcmp is +55
We now have to two new arrays (one for greater and one for less than).
$greater = array('img1', 'img10', '3.14', '2.72);
$less = array(2, 1, 1.5);
Now there is little need to go into further detail as we have accidentally made 2 arrays that have all easily comparable objects in it. $greater
has only strings, and we can assume sort will work normally here and considering everything a string.
sort($greater);
var_dump($greater);
produces
array(4) {
[0]=>
string(5) "2.72"
[1]=>
string(4) "3.14"
[2]=>
string(4) "img1"
[3]=>
string(5) "img10"
}
This is what we expected and also the result above. We do the same with $lesser
$lesser = array(2, 1, 1.5);
sort($lesser);
var_dump($lesser);
we get
array(3) {
[0]=>
int(1)
[1]=>
float(1.5)
[2]=>
int(2)
}
Which is also expected. Now when we concat all three arrays together (for the sake of recursiveness I am calling 'img2' an array). We get the results above.
Array
(
[0] => 2.72
[1] => 3.14
[2] => img1
[3] => img10
[4] => img2
[5] => 1
[6] => 1.5
[7] => 2
)
To prove this point, you can follow the same process for this same array, but switch out the $arr[3]
with an integer.
$arr = array("img2", 1, "img1", 2, "img10", 1.5, "3.14", "2.72");
sort($arr);
var_dump($arr)
gives you a totally different result because the pivot changed from a string to an int causing the float strings to evaluate as floats.
array(8) {
[0]=>
string(4) "img1"
[1]=>
string(5) "img10"
[2]=>
string(4) "img2"
[3]=>
int(1)
[4]=>
float(1.5)
[5]=>
int(2)
[6]=>
string(4) "2.72"
[7]=>
string(4) "3.14"
}
The following bug gives more insight in sorting mixed types: https://bugs.php.net/bug.php?id=21728
Quote:
<?php
$arr1 = array("a","b","c","d","4",5,4,"true","TRUE",true);
sort($arr1);
var_dump($arr1);
?>
The output is :
array(10) {
[0]=>
bool(true)
[1]=>
int(4)
[2]=>
string(1) "4"
[3]=>
string(4) "TRUE"
[4]=>
string(1) "a"
[5]=>
string(1) "b"
[6]=>
string(1) "c"
[7]=>
string(1) "d"
[8]=>
string(4) "true"
[9]=>
int(5)
}
It may look strange - why (int)5 is after all the strings. This is because "4" is lower than (int) 5, "4" is before "true" and "true" is before 5. The first 2 are obvious, the third one is not. But it is ok. It's better not to mix types in the array. If 5 is changed to "5" then "5" goes right after "4".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With