ksort

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : ksort

Re: ksort

par lmaltier » 03 sept. 2013, 14:03

Merci beaucoup pour ces rappels. Je suis surpris, parce que dans mon cas réel, je n'avais pas rempli le tableau à la main, bien sûr, et j'avais vérifié le type string des clés au cours de mes tests. Mais je n'avais peut-être pas vérifié pour absolument tous les éléments du tableau. C'est donc certainement l'explication, il y avait bien quelque chose qui m'échappait. On peut même comprendre que la clé '1/2' se retrouve avant la clé '1/1' (alors qu'elle devrait être après), et que la clé '1' (devenue entière) puisse être entre les deux : en effet, en cas de comparaison entre un nombre et un string, le string est converti en nombre avant la comparaison. Il reste que :
- c'est très trompeur de se retrouver avec un tri complètement en numérique flottant alors qu'on n'avait utilisé au départ que des strings.
- la doc est mal écrite : il faudrait écrire non pas "Strings containing valid integers will be cast to the integer type." mais "Strings containing valid integers written in the decimal notation will be cast to the integer type."

Re: ksort

par xTG » 03 sept. 2013, 13:42

Une fois de plus, le typage mou de PHP montre toutes ses faiblesses, d'autant qu'on ne voit pas pourquoi "01" ne serait pas un nombre...
"01" est une string jusqu'à preuve du contraire, ce serait pour le coup plus une preuve de typage fort si on voulait être ironique. ;)
01 est un entier en base 8.
1 est un entier en base 10.

L'exécution de :
$a = array( "1/1" => 1, "01" => 1, "1/2" => 1);

foreach ($a as $key => $value) {
print_r(gettype($key));
}
Affichera string. ;)

Et donc tout tri sera effectué sur le code ASCII des caractères si on ne demande pas un cast en entier.
Donc pourquoi ne pas utiliser le flag SORT_NUMERIC puisqu'il est question de cast en nombre ?

Re: ksort

par Pitet » 03 sept. 2013, 12:32

Le typage faible de PHP n'est pas une faiblesse, il faut savoir l'utiliser correctement.

"01" est bien un nombre, mais ce n'est pas un entier : le 0 en premier caractère indique une notation octale (http://www.php.net/manual/en/language.types.integer.php).

Même si certains comportement de PHP nous semble étrange, ils sont tout à fait corrects tant que la documentation officielle les justifie.

Re: ksort

par sirakawa » 03 sept. 2013, 11:29

Une fois de plus, le typage mou de PHP montre toutes ses faiblesses, d'autant qu'on ne voit pas pourquoi "01" ne serait pas un nombre...

Re: ksort

par Pitet » 03 sept. 2013, 10:38

Salut,

Essayez ceci :
$a = array( "1/1" => 1, "1" => 1, "1/2" => 1);

foreach ($a as $key => $value) {
	print_r(gettype($key));
}
La clé "1" est directement convertie en integer à l'affectation du tableau.
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.
(http://php.net/manual/en/language.types.array.php)

Puisque par défaut ksort() ne modifie pas les types des clés, il va devoir comparer une clé de type string avec un clé de type integer, c'est à ce moment que les clés string sont converties en numérique selon le principe de la conversion des chaines en nombres (http://www.php.net/manual/fr/language.t ... conversion).

Le comportement de ksort() est donc normal puis le soucis vient de l'affectation du tableau.

En modifiant la clé "1" par "01", on retrouve le comportement attendu.
<?php
$a = array( "1/1" => 1, "01" => 1, "1/2" => 1);

foreach ($a as $key => $value) {
print_r(gettype($key));
}

ksort($a, SORT_REGULAR);
print_r($a);
ksort($a, SORT_STRING);
print_r($a);

?>


Bonne journée

Re: ksort

par lmaltier » 03 sept. 2013, 08:42

Exactement, et c''est aussi l'hypothèse que j'ai faite. Mais c'est quand même incroyable... Si quelqu'un pouvait essayer avec la dernière version de PHP disponible pour voir si c'est encore la même chose ou si le problème est réglé...

Re: ksort

par sirakawa » 03 sept. 2013, 08:26

Par défaut c'est SORT_REGULAR : compare les éléments normalement (ne modifie pas les types)
Est-ce que "1/2" malgré les quotes est considéré comme un nombre? je ne saurais dire...

Re: ksort

par lmaltier » 03 sept. 2013, 08:02

Non, je veux bien des clés chaînes de caractères, le résultat de ksort($a, SORT_STRING); qui est Array ( [1] => 1 [1/1] => 1 [1/2] => 1 ), est donc parfaitement correct.

Mon problème est que, si je ne mets pas le paramètre SORT_STRING, le tri est incorrect, alors qu'il devrait être strictement identique avec ou sans le paramètre puisque les clés sont dans les deux cas des chaînes de caractères. J'ai perdu pas mal de temps avec ça, et j'ai donc trouvé le contournement (mettre SORT_STRING), mais le comportement sans le SORT_STRING est tout à fait anormal, à première vue. Je sais que ça semble énorme et invraisemblable comme bug PHP, et pourtant...

Re: ksort

par sirakawa » 11 août 2013, 11:27

maintenant, si on veut que l'ordre soit 1/2, 1, 2/1 il faudrait peut-être utiliser des cleis numériques?

Re: ksort

par xTG » 10 août 2013, 18:51

1/2 se trouve bien après 1/1 par rapport à leurs caractères ascii respectifs.

Si tu prends le caractère ascii X comme étant celui de 1 et Y comme étant celui de / alors voilà les chaînes que nous avons :
1/1 = X Y X
1/2 = X Y (X+1)

X+1 est bien après X non ? :)

Re: ksort

par sirakawa » 10 août 2013, 18:20

mon test :
<?PHP
$a = array( "a" => 1, "c" => 1, "b" => 1);
$b = $a;
ksort($a);
print_r($a);
ksort($a);
print_r($a);
?>
conclut au bon fonctionnement quand il s'agit d'une "vraie" chaîne
et idem ici:
<?PHP
$a = array( "1" => 1, "1/2" => 1, "2/1" => 1);
$b = $a;
ksort($a);
print_r($a);
ksort($a);
print_r($a);
?>

ksort

par lmaltier » 09 août 2013, 14:06

Bonjour,

Quelqu'un pourrait-il me dire ce qui m'échappe ? J'utilise la version PHP 5.4.3

Programme :

$a = array( '1/1' => 1, '1' => 1, '1/2' => 1);
ksort($a);
print_r($a);
ksort($a, SORT_STRING);
print_r($a);

résultat (illogique, on devrait avoir deux fois le même tableau, car par défaut, ksort est censé ne pas changer les types des clés, et les clés sont des chaînes de caractères) :

Array ( [1/2] => 1 [1] => 1 [1/1] => 1 ) Array ( [1] => 1 [1/1] => 1 [1/2] => 1 )

Merci de votre aide.