Forum Programmation.php bug PHP5 ou bug entre le clavier et la chaise ?

Posté par  (site web personnel) .
Étiquettes : aucune
0
7
avr.
2006
Bonjour,

je code en ce moment en PHP , et pour une fonction très particulière, je suis passé à PHP5 ( j'ai aussi d'autres raisons pour cette migration mais c'est une autre histoire ).

cette fonction est array_udiff() qui permet de calculer selon une contrainte utilisateur la difference entre N array .

Apres moults RTFM & STFW je conclus que GNEPMA ( Google N'Est Pas Mon Ami ), et je me tourne vers vous avant d'aller pleurer famine avec un bug report.

le probleme est simple, array_udiff ne me retourne pas ce que j'attends et les docs en ligne de php.net ( http://fr.php.net/manual/fr/function.array-udiff.php ) sont assez sybiline sur son fonctionnement.

soit le source suivant :

header( "Content-type: text/plain" );

$a1 = array(
array( "K1" => "v11", "K2" => "v21" ),
array( "K1" => "v12", "K2" => "v22" ),
array( "K1" => "v13", "K2" => "v23" ),
array( "K1" => "v14", "K2" => "v24" ),
array( "K1" => "v15", "K2" => "v25" )
);

$a2 = $a1;
$a2[1]["K1"] = "ick";
function mns_diffu_1( $a, $b ) {
return array_diff( $a, $b );
}

function mns_diffu_2( $a, $b ) {
return array_diff_assoc( $a, $b );
}

function mns_diffu_3( $a, $b ) {
return (count(array_diff( $a, $b )))?(1):(0);
}

function mns_diffu_algo( $a, $b ) {
print( $a["K1"] . " ? " . $b["K1"] . "\n" );
return array_diff( $a, $b );
}

print "affichage des differences\n";
print_r( $a1 );
print_r( $a2 );

print "affichage des differences\n";
print_r( array_udiff( $a2, $a1, "mns_diffu_1" ) );
print_r( array_udiff( $a2, $a1, "mns_diffu_2" ) );
print_r( array_udiff( $a2, $a1, "mns_diffu_3" ) );

print "affichage de l'algo\n";
print_r( array_udiff( $a2, $a1, "mns_diffu_algo" ) );

  • # C'est bien mais....

    Posté par  (site web personnel) . Évalué à 2.

    Si tu expliques pas le résultats que tu attends tu peut réver pour avoir une réponse.

    Donc explique bien la donnée de départ, la donnée souhaitée à l'arrivée et ce qui cloche avec le résultat obtenu.
    • [^] # Re: C'est bien mais....

      Posté par  (site web personnel) . Évalué à 2.

      $a1 et $a2 contiennent le meme tableau de tableau à 1 détail près : la valeur assigné à la clé K1 de la seconde ligne est différente.

      cf les deux lignes suivantes pour comprendre le contexte du probleme enoncé plus clairement dans la phrase d'au dessus :

      $a2 = $a1;
      $a2[1]["K1"] = "ick";


      array_udiff ne retourne pas la bonne valeur. c'est pour cela que j'affiche plusieurs essais différentes qui retourne le même résultat incohérent.

      le résultat attendu est "trouver que $a2[1] differe de $a1[1]". puisqu'encore une fois, c'est la seule différence introduite entre les 2 array() , et que c'est cette différence que j'attends de array_udfiff.

      si j'ai pondu un code source comme celui là, c'est pour montrer ou cela ne va pas sur un cas tres simple.

      il y a des jolis print() qui affichent des titres à ce qui sort, sur le premier, j'ai oublié de changer le nom il aurait du etre "affichage de $a1 et $a2" .

      je présume que tu as déjà lu le code source que j'ai fourni.

      Ces explications supplémentaires te permettent elles de me fournir une réponse à mon probleme ? ou un indice ?

      en tout cas, je te remercie de ta demande de précision qui pourra permettre d'éclaircir ce qui me semblait évident.
  • # Mauvaise compréhension des paramètres $a et $b

    Posté par  . Évalué à 2.

    Mais c'est vrai que sur ces fonctions, la doc php est parfois obscure (pour référence : http://fr2.php.net/manual/fr/function.array-udiff.php ).

    La fonction que tu donnes à array-udiff pour la comparaison (en l'occurence mns_diffu_algo) recoit deux paramètres, qui sont respectivement des valeurs provenant de l'un et de l'autre des tableaux. Pas des tableaux !

    Cette fonction doit retourner un résultat de type entier, dont la position par rapport à 0 va affecter le comportement du diff. Et le diff te retourne les éléments du premier tableau qui ne se retrouvent pas dans le deuxième.

    En l'occurence dans mns_diffu_algo, tu dois tester (en imaginant que $a et $b prennent successivement n'importe quelle valeur de chaque tableau) :

    Si $a == $b : return 0;
    Si $a > $b : return 1;
    Si $a < $b : return -1;

    PS : il semble important que la fonction fournie à array_udiff puisse retourner du positif et du négatif, d'ou l'intérêt de comparer des valeurs numériques exclusivement (donc peut-être se débarasser du 'v' avant le test).
    • [^] # Re: Mauvaise compréhension des paramètres $a et $b

      Posté par  (site web personnel) . Évalué à 2.

      mns_diffu_3 retourne 0 ou 1 selon les parametres.
      
      mes 2 arguments $a et $b sont bien 2 array puisque mns_diffu_algo affiche bien la valeur des clé K1 pour chacun des arrays en argument.
      
      
      j'attends juste un truc du genre :
      
      Array
      (
          [1] => Array
              (
                  [K1] => ick
                  [K2] => v22
              )
      )
      
      
      
      
      voici la trace que j'ai :
      
      
      affichage des array $a1 et $a2
      
      Array
      (
          [0] => Array
              (
                  [K1] => v11
                  [K2] => v21
              )
      
          [1] => Array
              (
                  [K1] => v12
                  [K2] => v22
              )
      
          [2] => Array
              (
                  [K1] => v13
                  [K2] => v23
              )
      
          [3] => Array
              (
                  [K1] => v14
                  [K2] => v24
              )
      
          [4] => Array
              (
                  [K1] => v15
                  [K2] => v25
              )
      
      )
      
      
      Array
      (
          [0] => Array
              (
                  [K1] => v11
                  [K2] => v21
              )
      
          [1] => Array
              (
                  [K1] => ick
                  [K2] => v22
              )
      
          [2] => Array
              (
                  [K1] => v13
                  [K2] => v23
              )
      
          [3] => Array
              (
                  [K1] => v14
                  [K2] => v24
              )
      
          [4] => Array
              (
                  [K1] => v15
                  [K2] => v25
              )
      
      )
      
      
      
      affichage des differences
      
      Array
      (
          [0] => Array
              (
                  [K1] => v11
                  [K2] => v21
              )
      
          [1] => Array
              (
                  [K1] => ick
                  [K2] => v22
              )
      
          [2] => Array
              (
                  [K1] => v13
                  [K2] => v23
              )
      
          [4] => Array
              (
                  [K1] => v15
                  [K2] => v25
              )
      
      )
      
      Array
      (
          [0] => Array
              (
                  [K1] => v11
                  [K2] => v21
              )
      
          [1] => Array
              (
                  [K1] => ick
                  [K2] => v22
              )
      
          [2] => Array
              (
                  [K1] => v13
                  [K2] => v23
              )
      
          [4] => Array
              (
                  [K1] => v15
                  [K2] => v25
              )
      
      )
      
      Array
      (
          [0] => Array
              (
                  [K1] => v11
                  [K2] => v21
              )
      
          [1] => Array
              (
                  [K1] => ick
                  [K2] => v22
              )
      
          [2] => Array
              (
                  [K1] => v13
                  [K2] => v23
              )
      
          [4] => Array
              (
                  [K1] => v15
                  [K2] => v25
              )
      
      )
      
      
      affichage de l'algo
      
      v13 ? ick
      v13 ? v11
      v13 ? v14
      v15 ? v13
      ick ? v14
      v11 ? ick
      v13 ? v12
      v13 ? v11
      v13 ? v14
      v15 ? v13
      v12 ? v14
      v11 ? v12
      v14 ? v14
      v14 ? ick
      ick ? v12
      ick ? v11
      ick ? v13
      ick ? v15
      ick ? v11
      v11 ? v13
      v13 ? v15
      
      Array
      (
          [0] => Array
              (
                  [K1] => v11
                  [K2] => v21
              )
      
          [1] => Array
              (
                  [K1] => ick
                  [K2] => v22
              )
      
          [2] => Array
              (
                  [K1] => v13
                  [K2] => v23
              )
      
          [4] => Array
              (
                  [K1] => v15
                  [K2] => v25
              )
      
      )
      
      • [^] # Re: Mauvaise compréhension des paramètres $a et $b

        Posté par  . Évalué à 2.

        <?php
        header( "Content-type: text/plain" );
         
         $a1 = array(
         array( "K1" => "v11", "K2" => "v21" ),
         array( "K1" => "v12", "K2" => "v22" ),
         array( "K1" => "v13", "K2" => "v23" ),
         array( "K1" => "v14", "K2" => "v24" ),
         array( "K1" => "v15", "K2" => "v25" )
         );
         
         $a2 = $a1;
         $a2[1]["K1"] = "ick";
        
        
         print "affichage de l'algo\n";
         print_r( array_udiff( $a2, $a1, "covalence_algo" ) );
         
        function covalence_algo($a,$b){
        	$_a=sprintf(crc32($a["K1"].$a["K2"]));
        	$_b=sprintf(crc32($b["K1"].$b["K2"]));
        
        	if($_a==$_b) return 0;
        	if($_a>$_b) return 1;
        	if($_a<$_b) return -1;
        }
        ?>
        
        • [^] # Re: Mauvaise compréhension des paramètres $a et $b

          Posté par  . Évalué à 2.

          Tu peux même te passer du sprintf.... Cela renvoie le résultat attendu:
          affichage de l'algo
          Array
          (
              [1] => Array
                  (
                      [K1] => ick
                      [K2] => v22
                  )
          
          )
          
          
          • [^] # Re: Mauvaise compréhension des paramètres $a et $b

            Posté par  (site web personnel) . Évalué à 2.

            cool merci pour la piste :)

            merci de cette réponse mon seul soucis est le risque de collisions puisque j'ai de gros volumes, je vais voir avec du SHA1. a mixer avec serialize() ca peut le faire de maniere sympathique :)

            maintenant, il y a de la doc implicite sur de l'usage avec des listes objets ... et comme PHP passe par copie de valeur les aguments, je ne pense pas que cela gene.

            bon, il y a en dessous un post que je viens de finir en étant un peu bougon ...
            je dois dire que je l'ai commencé dans la foulé du précedent pour le completer avec d'autres informations, et avec l'expression d'un sentiment d'absence de réponse.

            mais tu m'as répondu avec une piste et je me sens maintenant bien bete :|

            encore merci.
            • [^] # Re: Mauvaise compréhension des paramètres $a et $b

              Posté par  . Évalué à 2.

              merci de cette réponse mon seul soucis est le risque de collisions puisque j'ai de gros volumes, je vais voir avec du SHA1. a mixer avec serialize() ca peut le faire de maniere sympathique :)

              En effet, dans l'exemple que je te donne, le risque de collision existe mais est quasi nul sur le petit jeu de données fourni... Si tu as de gros volumes à traiter, je te conseille d'insérer entre les deux chaines une autre chaine qui ne court pas (trop) de risque de collision (c'est juste pour les besoins d'une comparaison, la chaine résultante est sans importance), comme ceci : crc32($a["K1"].'@!§%£'.$a["K2"]). Avec serialize tu risques d'avoir un impact beaucoup plus lourd sur les performances de l'ensemble, en particulier sur un gros volume.

              Et sha1 n'est peut-être pas très adapté pour faire une comparaison numérique ;-) c'est pour cela que je t'ai suggéré crc32, qui renvoie des entiers signés.
      • [^] # Re: Mauvaise compréhension des paramètres $a et $b

        Posté par  (site web personnel) . Évalué à 1.

        j'oubliais de préciser que http://bugs.php.net n'a aucune entrée et que http://bugs.php.net utilise des objets en argument de array_udiff.

        j'espere que cette longue trace coupera court à toute tentative de réponse sans avoir lu et testé mon bout de code.

        pour ceux qui ont encore un doute ( et je vais finir par paraitre plus execrable que je ne le suis réellement :) ) sur la lecture de mon bout de code :

        - je crée un tableau $a1.
        - je copie $a1 dans $a2.
        - je change 1 valeur dans $a2.
        - je déclare 4 fonctions mns_diffu_1 mns_diffu_2 mns_diffu_3 mns_diffu_algo .
        - je teste chacune des fonctions avec array_udiff et j'en affiche le résultat via un print_r ( print recursif de PHP ).

        mes fonctions sont :

        - mns_diffu_1( $a, $b ) qui retourne le array_diff entre $a et $b
        - mns_diffu_2( $a, $b ) qui retourne le array_diff_assoc entre $a et $b
        - mns_diffu_3( $a, $b ) qui retourne 1 si le array_diff entre $a et $b est non vide sinon 0
        - mns_diffu_algo( $a, $b ) qui affiche les K1 respective de $a et $b et retourne leur array_diff

        toutes ces fonctions fonctionnent, dans un contexte neutre
        print_r( mns_diffu_1( array( 1, 2, 3 ), array( 3, 1, 4 ) ) );

        Je ne dis pas que j'ai mis tous les tests possibles puisqu'il y en a d'autres, mais je n'ai pas trouvé d'autres plus significatif . il se peut aussi que j'en ai oublié un test qui aurait pu etre significatif.

        Tout ca pour dire que mon probleme n'est pas un probleme de "je suis en train d'apprendre à coder" mais un truc un peu plus couillu pour du code libre sur mon temps libre.

        pour donner le contexte, j'ai un formulaire en ligne à champs variables, et les anciennes valeurs dans une bases ... ce bout de code viendra juste faire "le diff entre ce que j'ai deja et ce que je vais avoir de nouveau" pour permettre de mettre a jour les bons champs, effacer ceux qui le doivent et ajouter ce qui le doivent.

        est ce que cela aide ? non.

        mes questions sont :

        - est ce le role de array_udiff de faire un diff entre deux listes selon une regle de l'utilisateur ? et je présuppose que oui d'apres la doc.

        - est ce un bug de array_udiff ? je suppute que oui avec moins de certitude car la doc n'est pas clair et que j'ai pu faire un mauvais usage de la fonction.

        j'ai donc l'impression d'etre désagréable, alors que le probleme est sérieux et que je n'ai pas une once d'élément de réponse à part un semblant de "ta pas bien lu la doc".

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.