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 :

hash de hash


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 45
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Par défaut hash de hash
    Bonjour à tous,


    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
    	# hash Characteristics[StdInChIKey]
    	# hash de hash, key1 : $Compound and key2 : corresponding $StdInChIKey  (we have to find only one k2 per k1)
    	my %comp_tab;
    	for my $i (1..$#tab){
    		my $Compound = $tab[$i][$Compound_index];
    		my $StdInChIKey = $tab[$i][$StdInChIKey_index];
     
    		next if (($Compound eq '') or ($StdInChIKey eq ''));
    		$Compound = lc($Compound);
    		$comp_tab{$Compound}{$StdInChIKey}++;
    	}
     
    	# check if we have only one K2 : $StdInChIKey per K1 : $Compound
    	foreach my $Compound (keys %comp_tab){
    		my $StdInChIKey_num = (keys %{$comp_tab{$Compound}});
    		if ($StdInChIKey_num > 1){
    			print "ERROR : $rep\t$Compound\n";
    		}
    	}
    J'ai 2 colonnes dans un tableau, $Compound et $StdInChIKey, contenant chacune le même nombres de valeurs.
    Je veux vérifier que pour chaque valeur de Compound, j'ai un StdInChIKey unique.
    Je place donc Compound en première clé du hash, StdInChIKey en seconde clé dans un hash imbriqué.
    Je vérifie ensuite, que pour chaque clé Compound, une seule entrée existe dans StdInChIKey.

    Cela fonctionne très bien, mais je me demandais comment aurais-je pu faire plus simple.
    N'hésiter pas à me poser des question si cela n'est pas clair.

    D'avance merci pour votre aide.

  2. #2
    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
    Billets dans le blog
    1
    Par défaut
    Bonjour Jasmine,

    cela me paraît être une bonne manière de faire.

    Toutefois, il serait peut-être possible de simplifier en utilisant un hash simple dont les clés serait des concaténations de $Compound et $StdInChIKey (avec de préférence un séparateur qui ne risque pas de se trouver dans le contenu de ces deux variables, j'ai mis ci-dessous un point-virgule, modifie en fonction de tes données). Quelque chose comme cela (non testé, pas de données):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	my %comp_tab;
    	for my $i (1..$#tab){     # es-tu sûre que ça ne commence pas à 0?
    		my $Compound = $tab[$i][$Compound_index];
    		my $StdInChIKey = $tab[$i][$StdInChIKey_index];
     
    		next if (($Compound eq '') or ($StdInChIKey eq ''));
    		$Compound = lc $Compound;
    		$comp_tab{"$Compound;$StdInChIKey"}++;
    	}
     
    	# check if we have only one K2 : $StdInChIKey per K1 : $Compound
    	print "ERROR : $rep\t$_\n" for map {my $c = (split /;/)[0]; $c} grep {$comp_tab{$_} > 1;} keys %comp_tab;

  3. #3
    Membre éprouvé
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 45
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Par défaut
    Bonjour Lolo,

    Je te remercie pour ton intervention.

    Par exemple, dans ces 3 $Compound;$StdInChIKey, je veux afficher l'erreur que Chlorobenzene possède 2 StdInChIKey différentes, ce qui est incorrect

    exeemple de clés :
    ---------------------------
    Chlorobenzene;MVPPADPHJFYWMZ-UHFFFAOYSA-N
    Chlorobenzene;GVPFVAHMJGGAJG-UHFFFAOYSA-L
    Diethyl maleate;IEPRKVQEAMIZSS-WAYWQWQTSA-N

    J'aurai donc 2 clés différentes : Chlorobenzene;MVPPADPHJFYWMZ-UHFFFAOYSA-N et Chlorobenzene;GVPFVAHMJGGAJG-UHFFFAOYSA-L
    => chacune avec $comp_tab{$_} == 1 ... si j'ai bien compris ton code, je ne pense pas que cela fera ce que je veux, car elles ne seront pas détectées en tant qu'erreur car elles sont toutes 2 des clés uniques

    Merci et bon week-end,

  4. #4
    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
    Billets dans le blog
    1
    Par défaut
    Hum,

    je n'ai donc pas tout compris à ton problème, mais je continue à penser que c'est probablement la solution.

  5. #5
    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
    Billets dans le blog
    1
    Par défaut
    Bonjour Jasmine,

    je relis attentivement ce que tu cherches à faire, et, si j'ai finalement bien compris à la lumière de ton dernier message, clairement, ce que j'avais proposé n'est pas la solution.

    Je continue à penser, cependant, que le hash de hash, bien que ce soit une solution possible, n'est pas la solution la plus simple et n'est pas indispensable, et qu'un simple hash est sans doute suffisant: dès que tu vois une clef et une valeur, tu la mets dans un hash, dès que tu revois la même clef, tu imprimes un message d'erreur si la valeur est différente, tout cela en une seule passe. Un truc dans ce genre (toujours pas testé, faute de données de test significatives):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	my %comp_tab;
    	for my $i (1..$#tab){     # es-tu sûre que ça ne commence pas à 0?
    		my $Compound = $tab[$i][$Compound_index];
    		my $StdInChIKey = $tab[$i][$StdInChIKey_index];
    		next if (($Compound eq '') or ($StdInChIKey eq ''));
    		$Compound = lc $Compound;
    		if (exists $comp_tab{$Compound}) {
    			print "ERROR : $rep\t$Compound\n" if  $comp_tab{$Compound} ne $StdInChIKey;   #  je suppose que ce n'est pas une erreur si on trouve deux fois la même valeur
    		} else {
    			$comp_tab{$Compound} = $StdInChIKey;
    		} 
    	}

  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
    Pour ce genre de besoin, j'utilise à la place un hash de array.
    Il est facile alors de trouver les clés pour lesquelles il y a plusieurs valeurs. Et lorsque la consommation mémoire devient critique (sur de très gros échantillon), j'utilise un hash de (scalaire ou array : scalaire pour le premier éléments, que je transforme en array si un nouvel élément devait être ajouté).
    Et quand la consommation mémoire devient vitale, j'utilise un hash de scalaire (clés de 2e ordre concaténées avec join "\x0" par exemple).

    Exemple hash de array :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    my %std_in_chi_key;
    while (defined(my $compound = <$COMPOUND>)) {
      chomp($compound);
      chomp(my $std_in_chi_key = <$STDINCHIKEY>);
      push @{$std_in_chi_key{$compound}}, $std_in_chi_key;
    }
     
    warn "The following Compound have several StdInChiKeys :", join ", ", grep @{$std_in_chi_key{$_}}>1, keys %std_in_chi_key;
    (attention, j'ai testé ce code très rapidement).

    Si tu es intéressé par les deux autres approches, je peux développer.

  7. #7
    Membre éprouvé
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 45
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Par défaut
    Bonjour Lolo,


    Citation Envoyé par Lolo78 Voir le message
    Bonjour Jasmine,

    je relis attentivement ce que tu cherches à faire, et, si j'ai finalement bien compris à la lumière de ton dernier message, clairement, ce que j'avais proposé n'est pas la solution.

    Je continue à penser, cependant, que le hash de hash, bien que ce soit une solution possible, n'est pas la solution la plus simple et n'est pas indispensable, et qu'un simple hash est sans doute suffisant: dès que tu vois une clef et une valeur, tu la mets dans un hash, dès que tu revois la même clef, tu imprimes un message d'erreur si la valeur est différente, tout cela en une seule passe. Un truc dans ce genre (toujours pas testé, faute de données de test significatives):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	my %comp_tab;
    	for my $i (1..$#tab){     # es-tu sûre que ça ne commence pas à 0?
    		my $Compound = $tab[$i][$Compound_index];
    		my $StdInChIKey = $tab[$i][$StdInChIKey_index];
    		next if (($Compound eq '') or ($StdInChIKey eq ''));
    		$Compound = lc $Compound;
    		if (exists $comp_tab{$Compound}) {
    			print "ERROR : $rep\t$Compound\n" if  $comp_tab{$Compound} ne $StdInChIKey;   #  je suppose que ce n'est pas une erreur si on trouve deux fois la même valeur
    		} else {
    			$comp_tab{$Compound} = $StdInChIKey;
    		} 
    	}
    Oui, cela commence bien à 1 car 0 est la première ligne du fichier, les en-tête de colonne que je veux passer (mais dont j'ai eu besoin antérieurement)
    Cette idée effectue ce que je veux.


    Merci.

Discussions similaires

  1. Parcours d'un hash de hash de hash
    Par ngere dans le forum Langage
    Réponses: 5
    Dernier message: 06/07/2005, 09h53
  2. Réponses: 6
    Dernier message: 05/07/2005, 11h05
  3. Réponses: 2
    Dernier message: 09/03/2005, 14h35
  4. [langage] hash de hash
    Par Kinethe dans le forum Langage
    Réponses: 17
    Dernier message: 27/08/2004, 13h22
  5. [langage] probleme avec un hash de hash
    Par planetevoyage dans le forum Langage
    Réponses: 4
    Dernier message: 06/06/2003, 12h55

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