Ubron Cinzento Ubron Cinzento - 1 year ago 110
PHP Question

ordering strings and numbers in php

I was experimenting with PHP type juggling and found a weired behavior I can't explain. I was sorting objects based on a property that is sometimes a string, sometimes a number. Using usort, some items get out of place. I can't figure out why. I'm using PHP 7.0.16.

class Classe {
protected $data = array();
public function Set($chave, $valor) {
$this->data[$chave] = $valor;
}
public function Get($chave) {
return $this->data[$chave];
}
}
$objetos = array();
$nomes = array('Joao', 'Jose', 'Lucas', 'Antonio', 'Miguel', 'Arthur', 'Davi', 'Bernardo', 'Heitor', 'Gabriel');
$posicoes = array(7, '8.2', '9', 1.0, '5', 1.1, '3.2', '2', '4', 4.2);
for ($i = 0; $i < 10; ++$i) {
$objeto = new Classe;
$objeto->Set('pos', $posicoes[$i]);
$objeto->Set('nome', $nomes[$i]);
$objetos[] = $objeto;
}
foreach ($objetos as $o) {
echo "{$o->Get('pos')}: {$o->Get('nome')}\n";
}
echo "\nAfter sorting:\n";
usort($objetos,
function($a, $b) {
return $a->Get('pos') - $b->Get('pos');
});

foreach ($objetos as $o) {
echo "{$o->Get('pos')}: {$o->Get('nome')}\n";
}


Order after sorting:


1: Antonio
1.1: Arthur
2: Bernardo
3.2: Davi
4: Heitor
5: Miguel
4.2: Gabriel
7: Joao
8.2: Jose
9: Lucas


Notice how items 4.2 and 5 are out of order. Why is that?

Answer Source

the problem is the float value. If you read the documentation you will find:

The comparison 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.

And:

Caution Returning non-integer values from the comparison function, such as float, will result in an internal cast to integer of the callback's return value. So values such as 0.99 and 0.1 will both be cast to an integer value of 0, which will compare such values as equal.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download