IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

perl objet problème avec l'instruction "sort"?


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 13
    Par défaut perl objet problème avec l'instruction "sort"?
    Bonsoir,

    j'utilise l'instruction sort pour trier un tableau csv à l'intérieur d'une méthode
    de classe qui utilise pour se faire une fonction (subroutine) qui elle
    ne peut à priori pas être une méthode de classe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @lines = sort CmpCsv @lines;
    La fonction CmpCsv ne peut par nature avoir des arguments et les clés de tri
    font parties des propriétés de l'objet.

    Pour que cette fonction puisse voir les propriétés de l'objet j'ai créé une variable de classe $ego que je valorise à $self.
    $ego est ensuite utilisée dans CmpCsv

    ça marche mais j'ai un problème de ré-entrance lorsque je crée de nouveau objet dans une des méthodes de l'objet lui-même (récursivité).

    Je peux imaginer des solutions de contournements qui sont des bidouilles
    pour me dépanner temporairement mais je ne vois pas comment
    faire cela proprement en respectant l'approche objet.


  2. #2
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Je n'ai rien compris...
    Dans la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @lines = sort CmpCsv @lines;
    Ou sont les objets ? Dans @lines ?

    La fonction fournie à sort possède toujours 2 paramètres dont les noms sont $a et $b. Ces deux paramètres sont "magiquement" initialisé par deux valeurs de la liste fournie en paramètre et qui sont à comparer (l'algorithme de tri s'occupe de choisir quels sont les éléments à comparer). La fonction retourne alors -1, 0, ou 1 selon que $a < $b, $a == $b ou $a > $b (selon les critères de tri élaboré dans la fonction).
    Ainsi, supposons que les éléments de @lines soient des objets dont une propriété id numérique est disponible par l'accesseur id(). Le tri selon cette propriété s'écriarait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    sub CmpCsv {
      return $a->id() <=> $b->id();
    }

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 13
    Par défaut ou est l'objet
    en fait on est dans l'objet

    les propriétés de l'objet sont en fait dans la fonction CmpCsv,
    (voir le tableau @cle_tri dans le code ci-dessous)
    mais atteinte via la variable ego pré-initialisé comme ceci: $ego=$self

    Le problème est que CmpCsv ne connait pas l'objet $self (puisque ce
    n'est pas une méthode de l'objet)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    # <CmpCsv>(: fonction de comparaison pour la commande de tri)
    # $a et $b sont les variables de tri transmise par la commande de tri "sort"
    sub CmpCsv()
    {
     my @cle_tri = @{$ego->{cle_tri}}; #[cle_tri] tableau des critères colonnes de tri
     my $k_a;
     my $k_b;
     my$col_tri;
     @t_a = split (/$szSep/,$a.$szSep);
     @t_b = split (/$szSep/,$b.$szSep);
     
     # cas particulier des lignes d'entêtes: elles doivent rester en début de tableau
     if( index($t_a[0],"CSV_") > -1 && index($t_b[0],"CSV_") > -1 )
      {
       if( $csv_ordre{substr($t_a[0],0,8)} < $csv_ordre{substr($t_b[0],0,8)} ) {return -1;}
      }
     elsif( index($t_a[0],"CSV_TOT") > -1 ) {return 1;} # CSV_TOT en dernière position
     elsif( index($t_b[0],"CSV_TOT") > -1 ) {return -1;}
     elsif( index($t_a[0],"CSV_") > -1 ) {return -1;}
     elsif( index($t_b[0],"CSV_") > -1 ) {return 1;}
     else
      {
       # contruction des chaînes clé de comparaison.
       foreach  my $r_spe_tri (@cle_tri)
        {
         $col_tri = ${$r_spe_tri}[0];
         if(${$r_spe_tri}[3] == 0) # le critère de tri est une sous-chaîne
          {
           $elt_a = substr($t_a[$col_tri],${$r_spe_tri}[1],${$r_spe_tri}[2]);
           $elt_b = substr($t_b[$col_tri],${$r_spe_tri}[1],${$r_spe_tri}[2]);
          }
         else
          {
           $elt_a = $t_a[$col_tri];
           $elt_b = $t_b[$col_tri];
          }
         if(${$r_spe_tri}[4] == 1)
          {
           $k_a .= $elt_b;
           $k_b .= $elt_a;
          }
         else
          {
           $k_a .= $elt_a;
           $k_b .= $elt_b;
          }
        }
       # comparaison des chaînes clé
       $k_a cmp $k_b;
      }
    }

  4. #4
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Merci d'utiliser la balise CODE (icone ) pour encadrer ton source, c'est illisible là

  5. #5
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Votre code devrait être bien indenté pour également améliorer la lisibilité.
    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    # <CmpCsv>(: fonction de comparaison pour la commande de tri)
    # $a et $b sont les variables de tri transmise par la commande de tri "sort"
    sub CmpCsv() {
      my @cle_tri = @{ $ego->{cle_tri} };    #[cle_tri] tableau des critères colonnes de tri
      my $k_a;
      my $k_b;
      my $col_tri;
      @t_a = split( /$szSep/, $a . $szSep );
      @t_b = split( /$szSep/, $b . $szSep );
     
      # cas particulier des lignes d'entêtes: elles doivent rester en début de tableau
      if ( index( $t_a[0], "CSV_" ) > -1 && index( $t_b[0], "CSV_" ) > -1 ) {
        if ( $csv_ordre{ substr( $t_a[0], 0, 8 ) } < $csv_ordre{ substr( $t_b[0], 0, 8 ) } ) { return -1; }
      }
      elsif ( index( $t_a[0], "CSV_TOT" ) > -1 ) { return 1; }    # CSV_TOT en dernière position
      elsif ( index( $t_b[0], "CSV_TOT" ) > -1 ) { return -1; }
      elsif ( index( $t_a[0], "CSV_" ) > -1 )    { return -1; }
      elsif ( index( $t_b[0], "CSV_" ) > -1 )    { return 1; }
      else {
     
        # contruction des chaînes clé de comparaison.
        foreach my $r_spe_tri (@cle_tri) {
          $col_tri = ${$r_spe_tri}[0];
          if ( ${$r_spe_tri}[3] == 0 )                            # le critère de tri est une sous-chaîne
          {
            $elt_a = substr( $t_a[$col_tri], ${$r_spe_tri}[1], ${$r_spe_tri}[2] );
            $elt_b = substr( $t_b[$col_tri], ${$r_spe_tri}[1], ${$r_spe_tri}[2] );
          }
          else {
            $elt_a = $t_a[$col_tri];
            $elt_b = $t_b[$col_tri];
          }
          if ( ${$r_spe_tri}[4] == 1 ) {
            $k_a .= $elt_b;
            $k_b .= $elt_a;
          }
          else {
            $k_a .= $elt_a;
            $k_b .= $elt_b;
          }
        }
     
        # comparaison des chaînes clé
        $k_a cmp $k_b;
      }
    }

  6. #6
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Outre le fait que je n'ai toujours pas saisi la problématique initiale, ta fonction de comparaison élémentaire est beaucoup trop complexe.
    Je t'invite à considérer la technique de la transformée schwartzienne qui consiste à réaliser un prétraitement une seule fois sur l'ensemble du tableau (dans un map) et à retourner une liste de couples contenant la clé et l'objet à trier, réaliser le tri avec une fonction de tri simple (du type $a->[0] <=> $b->[0]) puis un deuxième map retournant à nouveau l'objet initial (du type map { $_->[1] })

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 13
    Par défaut merci pour l'optimisation
    Désolé pour l'indentation, ce n'est pas celle recommendée par le "C white book"
    mais elle ne différe que par le retour à la ligne avant le "{". Ceci parce j'utilise la commande % sous vim qui se déplace sur l'autre accolade du bloc et que j'essaye d'économiser mes yeux (moins de mouvement que si c'est en diagonale).

    Merci pour la méthode schwartzienne, ç ava aller plus vite.

    Pour la problèmatique :

    Dans une méthode objet l'objet est connu par self qui est transmis lors de l'appel comme premier argument $self->methode()

    on a dans la méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    sub methode()
     my $self = shift;
    mais avec la fonction de tri l'objet n'est pas transmis donc pas connu !

  8. #8
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Je ne vois toujours pas ce que tu veux trier ?!
    - des objets ?
    - des propriétés dans un objet ?
    - autre chose ?

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 13
    Par défaut
    Je tri un tableau CSV en spécifiant les colonnes de tri

    Le tableaux CSV est stocké dans un tableau perl: @lines

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       @lines = sort CmpCsv @lines;
    passé en argument à la méthode qui contient le code ci-dessus.

    Mais pour le tri c'est ok, je n'ai pas de problème, ça marche
    en mono-instance. Reste à optimiser avec Schartz.

  10. #10
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Donc il n'y a plus de problème de tri, juste d'optimisation, c'est bien cela ?

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 13
    Par défaut conclusion
    On va dire ça !

    Merci pour votre intervention.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Perl objet problème avec "prepare"
    Par Christophe53 dans le forum Langage
    Réponses: 2
    Dernier message: 08/03/2011, 11h06
  2. Formulaires : problème avec les slashes et les quotes
    Par GarGamel55 dans le forum Langage
    Réponses: 1
    Dernier message: 12/10/2005, 15h59
  3. Problème avec une instruction OUTER /Postgres
    Par Volcomix dans le forum Langage SQL
    Réponses: 14
    Dernier message: 21/04/2004, 16h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo