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 :

[langage] hash et tri


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 69
    Par défaut [langage] hash et tri
    salut, j'ai encore un problème avec mon hash.....

    j'ai un hash qui possède une clé de type :
    gi|19612490|gb|AAH49588.1|__122'
    'gi|19612490|gb|AAH49588.1|__12'
    'hi|19612490|gb|AAH49588.1|__114'
    'hi|19612490|gb|AAH49588.1|__113'
    'gi|19612490|gb|AAH49588.1|__112'
    'gi|19612490|gb|AAH49588.1|__111'
    'gi|19612490|gb|AAH49588.1|__110'
    'gi|19612490|gb|AAH49588.1|__11'
    'gi|19612490|gb|AAH49588.1|__108'
    'hi|19612490|gb|AAH49588.1|__11'
    'hi|19612490|gb|AAH49588.1|__106'
    'gi|19612490|gb|AAH49588.1|__105'
    cette clé est en fait composé de 2 éléments:

    gi|19612490|gb|AAH49588.1| et __11
    et j'aimerai pouvoir trier ce hash , d'abord par ordre alphabétique pour le 1er élément puis par ordre numérique pour le 2ème élément

    Pour cela, je dois utiliser la fonction ( je sais que ca marche avec!)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    sub byseq { 
      my ($a1,$a2) = split /___/,$a; ## split permet de separer avant ($a1) et apres ($a2) __ de $a, $a etant la cle du hash 
      my ($b1,$b2) = split /___/,$b; ## split permet de separer avant ($b1) et apres ($b2) __ de $b, $b etant la cle du hash 
     
      if ($a1 ne $b1) { return ($a1 cmp $b1); } 
      return ($a2-$b2); 
    }
    en fait cette fonction permet de à partir des deux clés:

    gi|19612490|gb|AAH49588.1|__11
    hi|19612490|gb|AAH49588.1|__109

    de séparer les deux éléments de la clé en $a1 pour gi|19612490|gb|AAH49588.1|, $a2 pour 11, $b1 pour hi|19612490|gb|AAH49588.1|, et $b2 pour 109

    puis on compare $a1 et $b1, puis $a2 et $b2

    mais le problème est que je n'arrive pas à faire le tri numérique.

    en fait : j'obtiens : pour la clé qui commence par hi 114, 113, 11, 106, et pour celle qui commence par gi 122, 111, 110, 11, 108, puis 105

    or je souhaite obtenir pour la clé qui commence par hi 114, 113, 106, 11 et pour celle qui commence par gi 122, 111, 110, 108, 105 et 11.

    voici mon code:


    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
     
    #!/usr/bin/perl
     
    use strict;
     
    my %hash = ('gi|19612490|gb|AAH49588.1|__122' => 20,
    'gi|19612490|gb|AAH49588.1|__12' => 21,
    'hi|19612490|gb|AAH49588.1|__114' => 12,
    'hi|19612490|gb|AAH49588.1|__113' => 212,
    'gi|19612490|gb|AAH49588.1|__112' => 2,
    'gi|19612490|gb|AAH49588.1|__111' => 5,
    'gi|19612490|gb|AAH49588.1|__110' => 4,
    'gi|19612490|gb|AAH49588.1|__11'=> 22,
    'gi|19612490|gb|AAH49588.1|__108' => 32,
    'hi|19612490|gb|AAH49588.1|__11' => 42,
    'hi|19612490|gb|AAH49588.1|__106' => 4,
    'gi|19612490|gb|AAH49588.1|__105' => 6,
    ); 
     
    sub byseq { 
    my ($a1,$a2) = split /___/,$a; ## split permet de separer avant ($a1) et apres ($a2) __ de $a, $a etant la cle du hash 
    my ($b1,$b2) = split /___/,$b; ## split permet de separer avant ($b1) et apres ($b2) __ de $b, $b etant la cle du hash 
     
    if ($a1 ne $b1) { return ($a1 cmp $b1); } 
    return ($a2 <=> $b2); 
    } 
     
    for my $key (reverse (sort { byseq ($a, $b) } keys (%hash))) { 
    print "$key\t\t$hash{$key}\n";
    }

    Merci d'avance

  2. #2
    Membre Expert
    Avatar de 2Eurocents
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 177
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 177
    Par défaut
    Deux choses :

    Dans ton "sub byseq", il faut récupérer les paramètres de l'appel :

    commencer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    my $a=shift;
    my $b=shift;
    Et dans tes splits, tu as un underscore de trop dans l'expression rationnelle.

    Enjoy Perl 8)

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 69
    Par défaut
    je ne comprends pas pourquoi j'ai un underscore de trop: il y en a 2 ds mes clés et 2 dans la fonction split?

    Dans ton "sub byseq", il faut récupérer les paramètres de l'appel :
    Normalement, je ne suis pas obligé de le faire car les fonctions "cmp" ou " <=>" retournent des valeurs par défaut, non?
    Elles renvoient -1,0 ou 1 selon que le premier argument est inférieur, égal ou supérieur au deuxième argument?????

    a+

  4. #4
    Membre Expert
    Avatar de 2Eurocents
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 177
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 177
    Par défaut
    Je compte 3 underscores dans les expr. de tes splits. J'ai dû en supprimer un pour qu'il fonctionne.

    J'en conclus logiquement qu'il y en a un de trop


    Pouyr les paramètres du sub myseq :
    $a et $b de l'appel sont des variables internes du sort. Tu les passes en paramètres à ta fonction de tri, mais il faut qu'elle les utilise ...

    Quand on arrive dans myseq, les valeurs de $a et $b sont rangées dans le tableau @_. $a est la première et $b est la seconde.

    Moi, j'ai l'habitude de toujours sortir les variables de ce tableau, pour travailler explicitement dessus. C'est pour cela que je te l'ai conseillé, mais c'est effectivement superflu, dans ton cas.

    Pour info, ce code marche très bien, chez moi

    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
     
    #!/usr/bin/perl -w
     
    use strict;
     
    my %hash = ('gi|19612490|gb|AAH49588.1|__122' => 20,
    'gi|19612490|gb|AAH49588.1|__12' => 21,
    'hi|19612490|gb|AAH49588.1|__114' => 12,
    'hi|19612490|gb|AAH49588.1|__113' => 212,
    'gi|19612490|gb|AAH49588.1|__112' => 2,
    'gi|19612490|gb|AAH49588.1|__111' => 5,
    'gi|19612490|gb|AAH49588.1|__110' => 4,
    'gi|19612490|gb|AAH49588.1|__11'=> 22,
    'gi|19612490|gb|AAH49588.1|__108' => 32,
    'hi|19612490|gb|AAH49588.1|__11' => 42,
    'hi|19612490|gb|AAH49588.1|__106' => 4,
    'gi|19612490|gb|AAH49588.1|__105' => 6,
    );
     
    sub byseq {
    my $a=shift;
    my $b=shift;
    my ($a1,$a2) = split /__/,$a; ## split permet de separer avant ($a1) et apres ($a2) __ de $a, $a etant la cle du hash
    my ($b1,$b2) = split /__/,$b; ## split permet de separer avant ($b1) et apres ($b2) __ de $b, $b etant la cle du hash
     
    if ($a1 ne $b1) { return ($a1 cmp $b1); }
    return ($a2 <=> $b2);
    }
     
    for my $key (reverse (sort { byseq ($a, $b) } keys (%hash))) {
    print "$key\t\t$hash{$key}\n";
    }

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 69
    Par défaut
    en effet, génial, ca marche!
    et puis oui tu as raison je viens de me rendre compte que j'avais 3 underscores et je pense que mon erreur venait donc de là!!!

    merci en tout cas


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

Discussions similaires

  1. [langage] hash et fonction
    Par perlaud dans le forum Langage
    Réponses: 5
    Dernier message: 21/09/2004, 19h54
  2. [langage] hash de hash
    Par Kinethe dans le forum Langage
    Réponses: 17
    Dernier message: 27/08/2004, 13h22
  3. [langage] Probleme de tri d'un tableau de tableau
    Par Ludo167 dans le forum Langage
    Réponses: 1
    Dernier message: 25/08/2004, 10h32
  4. [langage] personnaliser le tri
    Par schnecke dans le forum Langage
    Réponses: 3
    Dernier message: 24/03/2004, 15h14
  5. [langage] hash
    Par giverny dans le forum Langage
    Réponses: 3
    Dernier message: 12/08/2003, 11h27

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