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 :

Depiler un hash de références


Sujet :

Langage Perl

  1. #1
    Membre averti Avatar de sohnic
    Femme Profil pro
    bioinfo
    Inscrit en
    Mai 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : bioinfo

    Informations forums :
    Inscription : Mai 2003
    Messages : 426
    Points : 434
    Points
    434
    Par défaut Depiler un hash de références
    Bonjour,
    Je dois manipuler de très gros hash, ce qui cause des problèmes de mémoire. Une façon d'y remédier serait de stocker des références et là je me heurte à un problème.
    Un exemple simple pour éclaircir la situation:
    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
     
    use strict;
    my %tab;
    $tab{'a'}='a1';
    $tab{'b'}='b1';
    my $reftab=\%tab;
     
    my %tab2;
    $tab2{\$reftab->{'a'}}{\$reftab->{'b'}}=1;
    print '\$reftab->{\'a\'}='.\$reftab->{'a'}."\n";
    print '$reftab->{\'a\'}='.$reftab->{'a'}."\n";
     
    my $reftabtmp=\$reftab->{'a'};
    print "reftabtmp=$reftabtmp\n";
    my $valinreftabtmp=$$reftabtmp;
    print "valinreftabtmp=$valinreftabtmp\n";
    Retourne:
    \$reftab->{'a'}=SCALAR(0x2086240)
    $reftab->{'a'}=a1
    reftabtmp=SCALAR(0x2086240)
    valinreftabtmp=a1

    Jusque là tout va bien !

    Ajoutons maintenant une petite boucle, car bien sur mon but est ensuite de dépiler tab2 et de récupérer les valeurs stockées aux différentes adresses.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    foreach my  $ref1(keys %tab2)
    {
    	print "ref1=$ref1\n";	
    	my $element_at_ref1=$$ref1;
    	print "element_at_ref1=$element_at_ref1\n";
    }
    Ceci me retourne:
    ref1=SCALAR(0x2086240) Là, on d'accord, c'est cohérent
    Mais la suite est: Can't use string ("SCALAR(0x2086240)") as a SCALAR ref while "strict refs" in use
    Autrement dit, le comportement est différent dans une boucle.

    J'ai tenté en virant le use strict et les my, à la place element_at_ref1 est vide au lieu d'une erreur. Et pas plus de succès avec use Data:umper;

    Si quelqu'un voit ce qui cloche, il me rendrait vraiment service...

    Merci !
    S.
    http://www.noctinfo.fr/

    (\ _ /)
    (='.'=) Voici Lapinou. Aidez-le à conquérir le monde en le reproduisant.
    (")-(")

  2. #2
    Membre averti Avatar de sohnic
    Femme Profil pro
    bioinfo
    Inscrit en
    Mai 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : bioinfo

    Informations forums :
    Inscription : Mai 2003
    Messages : 426
    Points : 434
    Points
    434
    Par défaut
    Une piste: ref1 serait considéré comme une chaine de caractère et non comme une adresse...
    http://www.noctinfo.fr/

    (\ _ /)
    (='.'=) Voici Lapinou. Aidez-le à conquérir le monde en le reproduisant.
    (")-(")

  3. #3
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 238
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 238
    Points : 13 443
    Points
    13 443
    Par défaut
    Bonjour

    Tu as apporté la question et la réponse.

    Une piste: ref1 serait considéré comme une chaine de caractère et non comme une adresse...
    Ben oui. $ref1 est une chaîne de caractères.
    Quand tu écris keys %tab2, tu fais une liste des clés de ton tableau associatif (hash).
    Et quand tu prends un élément de cette liste, c'est donc une chaîne de caractères puisque les clés de tableau associatif sont des chaînes de caractères.

    $$ref1, dans ton esprit, doit pointer sur la valeur ?
    Mais pour cela, il faudrait que $ref1 soit une référence.
    Or ce n'est pas une référence.
    C'est une chaîne de caractères.
    Donc pas de sens.

    Est-ce plus clair ?
    Est-ce la question ?
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  4. #4
    Membre averti Avatar de sohnic
    Femme Profil pro
    bioinfo
    Inscrit en
    Mai 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : bioinfo

    Informations forums :
    Inscription : Mai 2003
    Messages : 426
    Points : 434
    Points
    434
    Par défaut
    Et oui, j'ai bien pointé le problème. Mais y-t-il moyen de typer cette variable en fait ? Parce que effectivement un string ne sera jamais un pointeur...
    Bref, la seule solution est-elle d'utiliser un langage typé (donc pas perl) ou existe-t-il une lib qui permettrait de faire un minimum de typage.
    En C on fait des tableaux de pointeurs couramment par exemple.

    S.
    http://www.noctinfo.fr/

    (\ _ /)
    (='.'=) Voici Lapinou. Aidez-le à conquérir le monde en le reproduisant.
    (")-(")

  5. #5
    Membre habitué
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Juillet 2014
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : Conseil

    Informations forums :
    Inscription : Juillet 2014
    Messages : 84
    Points : 197
    Points
    197
    Par défaut
    Pas le temps de tester ton problème, mais tu dois pouvoir trouver de l'aide ici -> https://perldoc.perl.org/functions/ref.html

    La fonction ref renvoie le 'type' de la donnée envoyée.

  6. #6
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 238
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 238
    Points : 13 443
    Points
    13 443
    Par défaut
    Citation Envoyé par sohnic Voir le message
    En C on fait des tableaux de pointeurs couramment par exemple.
    En C, les clés des tableaux sont des entiers. N'est-ce pas ?
    On ne met pas les pointeurs au milieu des clés.

    Ce n'est pas le langage qui a un problème. C'est ton code.
    Que cherches-tu vraiment à faire ?
    C'est plutôt ça, la vraie question.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  7. #7
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Citation Envoyé par sohnic Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    my %tab;
    $tab{'a'}='a1';
    $tab{'b'}='b1';
    my $reftab=\%tab;
     
    my %tab2;
    $tab2{\$reftab->{'a'}}{\$reftab->{'b'}}=1;
    Dans ce code, $reftab est déjà une référence vers %tab. Pourquoi ajoutes-tu un antislash devant chacun des deux $reftab dans la dernière ligne ci-dessus?

    Avec ton code, la structure de %tab2 est la suivante (avec Data:: Dumper):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $VAR1 = {
              'SCALAR(0x4ff31f0)' => {
                                       'SCALAR(0x4fff7a8)' => 1
                                     }
            };
    Si tu enlèves les deux antislashes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $tab2{$reftab->{'a'}}{$reftab->{'b'}}=1;
    La structure de %tab2 est maintenant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $VAR1 = {
              'a1' => {
                        'b1' => 1
                      }
            };
    Cela me paraît sans doute mieux correspondre à ce que tu as l'air de vouloir faire.

    Mais à vrai dire, je ne comprends pas bien ce que tu veux vraiment faire. Ce n'est pas parce que tu utilises des références vers les données de ton très gros hachage que tu vas réduire l’empreinte mémoire de tes données.

  8. #8
    Membre averti Avatar de sohnic
    Femme Profil pro
    bioinfo
    Inscrit en
    Mai 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : bioinfo

    Informations forums :
    Inscription : Mai 2003
    Messages : 426
    Points : 434
    Points
    434
    Par défaut
    Merci pour toutes vos contributions. Il y a des pistes intéressantes dans tout ça !
    J'essaie de tester tout ça la semaine prochaine.
    Difficile de vous expliquer dans le détail mon but. Il s'agit d'un projet de génomique et je n'ai pas trouvé d'autre façon que de démarrer par un ENORME hash (plusieurs millions d'éléments), les clefs étant des chaines de caractères.
    Je dois ensuite extraire des données par paire de ce hash (encore plus de millions !). Mon idée était donc de creer ce second tableau en stockant les paires d'adresses correspondant au premier hash et non les paires de chaines de caractères elles-mêmes.
    Flodelarab, oui tu as entièrement raison. C'était juste pour expliciter ce que je voulais (pouvoir typer mes variables). Si j'utilisais un tableau scalaire, j'aurais eu le même problème, non ? Les valeurs stockées dans mon tableau auraient été des chaines de caractères et non des pointeurs. Ou je me trompe ?

    En tout cas merci à tous, je ne pensais pas trouver autant d'idées sur ce coup là !
    Bonne journée,
    http://www.noctinfo.fr/

    (\ _ /)
    (='.'=) Voici Lapinou. Aidez-le à conquérir le monde en le reproduisant.
    (")-(")

  9. #9
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 238
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 238
    Points : 13 443
    Points
    13 443
    Par défaut
    Je dois ensuite extraire des données par paire de ce hash (encore plus de millions !). Mon idée était donc de creer ce second tableau en stockant les paires d'adresses
    Miam. Complexité quadratique (n2=n*n où n est le nombre d'entrée du premier hash).

    Pour le code, fais simple :

    En imaginant une fonction quantite() qui renvoie la quantité d'un motif, voici ce qu'on peut faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    foreach my $debut (keys %tab) {
        foreach my $fin (keys %tab) {
            $motif=$debut.$fin;
            $tab2{$motif}=quantite($motif);
        }
    }
    Si %tab a vraiment 1 million de brins, %tab2 aura 1 billion d'entrées ( = 1 000 000 000 000). Question d'algorithmie.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  10. #10
    Membre averti Avatar de sohnic
    Femme Profil pro
    bioinfo
    Inscrit en
    Mai 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : bioinfo

    Informations forums :
    Inscription : Mai 2003
    Messages : 426
    Points : 434
    Points
    434
    Par défaut
    Heureusement que ça n'est pas ce cas de figure ! Les paires sont sélectionnées sous condition ce qui réduit tout de même drastiquement le jeu de données. Sur un test simple, j'ai obtenu une selection de "seulement" 500 millions de paires à partir d'un jeu de 5 millions en entrée !
    http://www.noctinfo.fr/

    (\ _ /)
    (='.'=) Voici Lapinou. Aidez-le à conquérir le monde en le reproduisant.
    (")-(")

Discussions similaires

  1. tableau de tables de hash référence perl
    Par sbtrinity dans le forum Langage
    Réponses: 11
    Dernier message: 12/03/2012, 15h02
  2. Réponses: 3
    Dernier message: 23/05/2011, 15h18
  3. références de hash
    Par Jasmine80 dans le forum Langage
    Réponses: 13
    Dernier message: 19/02/2010, 13h23
  4. hash -> références
    Par mauroyb0 dans le forum Langage
    Réponses: 7
    Dernier message: 14/06/2006, 21h29
  5. Référence en retour de fonction, à transformer en hash
    Par raoulchatigre dans le forum Langage
    Réponses: 4
    Dernier message: 15/07/2005, 15h24

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