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 :

fusion de hashes avec clés communes


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    Octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : Octobre 2009
    Messages : 482
    Par défaut fusion de hashes avec clés communes
    Bonjour,

    J'ai un bout de code qui fonctionne, avec deux solutions, mais qui ne sont pas propres ni l'une ni l'autre, et une solution élégante mais que je n'arrive pas à faire fonctionner.

    La question est: comment faire fonctionner la solution "élégante" ?

    Merci d'avance

    --------------------------------------------
    Description (perl 5.10) :
    Les deux tableaux associatifs (hashes) à fusionner comportent des clés communes.
    Le premier tableau %hash_bool comporte des valeurs booléennes associées aux clés.
    Le second tableau %hash_datas comporte les valeurs à associer aux clés communes (aux 2 tableaux hash_bool et hash_datas).

    La subroutine est appelée de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my %hash_common = &hash_merge($merge_condition, @master_common_param, @master_values);
    @master_common_param et @master_values étant des hashes, $merge_condition n'etant qu'un booléen valant 1.

    1ere solution "élégante" mais que je n'arrive pas à faire fonctionner probablement à cause d'une mauvaise compréhension des références.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    sub hash_merge {
    my ($merge_condition, $hash_bool, $hash_datas) = @_ ;
    @hash_bool{ keys %$hash_datas } = values %$hash_datas;
    return  $hash_bool;
    }
    2eme solution, qui fonctionne, mais... beurk, pas belle:
    En effet, je recopie les tableaux passés en parametres pour les fusionner. Sinon, je n'arrive pas à accéder à leur contenu. Surement encore cette histoire de reference..
    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
    sub hash_merge {
    # input data: $hash_bool(true) x $hash_values = $hash_merged
    # constraint: keys from hash_bool being contained in $hash_datas
    # returns : merged hash
    	my ($merge_condition, $hash_bool, $hash_datas) = @_ ;
    	my %hash_merged;
     
     
    	# Sort hashes by key
    	sort keys %$hash_bool;
    	sort keys %$hash_datas;
     
    	# Duplicate the 2 hashes to tmp (direct access to the hashes does not work, direct copy neither ..)
    	my %tmp_bool;
    	my %tmp_data;
    	while ( my ($key, $value) = each(%$hash_datas) ) {
    		$tmp_data{$key} = $value ;
    	}
    	while ( my ($key, $value) = each(%$hash_bool) ) {
    		$tmp_bool{$key} = $value ;
    	}
     
    	# Merge the 2 tmp hashes if common existing keys and bool=true
    	while ( my ($key, $value) = each(%tmp_bool) ) {
    		if (exists ($tmp_data{$key}) && $value eq $merge_condition ) {
    			$hash_merged{$key} = $tmp_data{$key} ;
    		}
    	}
     
    	return %hash_merged;
     
    } # end SUB
    3eme solution: de loin la plus moche, je balaie (hum n x n fois en plus) les 2 tableaux d'entrée avec 2 boucles "while" imbriquées et j'utilise un 3eme tableaux pour le resultat. ça fonctionne mais là, c'est vraiment pas beau et consommateur de ressources.

    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
    sub hash_merge {
    # input data: $hash_bool(true) x $hash_values = $hash_merged
    # constraint: keys from hash_bool being contained in $hash_datas
    # returns : merged hash
    	my ($merge_condition, $hash_bool, $hash_datas) = @_ ;
    	my %hash_merged;
     
     
    	# Sort hashes by key
    	sort keys %$hash_bool;
    	sort keys %$hash_datas;
     
    	while ( my ($key, $value) = each %$hash_bool) {
    		if ($value eq $merge_condition) {
    			while ( my ($key2, $value2) = each %$hash_datas) {
    				if ($key2 eq $key) {
    				# print "merging : $key, $value2\n" ;
    				$hash_merged{$key} = $value2;
    				}
    			}
    		}
    	}
    	return %hash_merged ;

  2. #2
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2011
    Messages
    184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 184
    Par défaut
    Je ne sais pas si j'ai bien compris. Donc, j'ai écrit un code qui me semble correspondre à ce que tu veux.

    Si j'ai bien compris, le but du jeu est de récupérer une hash contenant seulement les couples de hash_datas (h_d pour moi) pour lesquels les clés pointent vers la valeur merge_condition dans hash_bool (h_b pour moi). C'est ça ?

    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
     
    my %h_b = (
      1 => 1,
      2 => 0,
      3 => 1,
      4 => 0,
      5 => 1,
    );
     
    my %h_d = (
      1 => 24,
      4 => 12,
      5 => 56,
    );
     
    my %res =  merge(1,\%h_b,\%h_d);
    while(my ($k,$v) = each(%res)) {
      print "$k -> $v\n";
    }
     
     
    sub merge {
    my ($merge_condition, $b, $d) = @_ ;
    foreach(keys %$d) {
      if($$b{$_}==$merge_condition) {
        $res{$_} = $$d{$_}
      }
    return  %res;
    }
    Une simple boucle suffit, du coup.
    C'est également possible en plus court avec un map :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    map(($$b{$_}==$merge_condition and $res{$_} = $$d{$_}),keys(%$d));
    En espérant ne pas mettre tromper...

  3. #3
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    Octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : Octobre 2009
    Messages : 482
    Par défaut
    Bonjour Dimity,

    Hum non pas exactement :

    Voilà les 2 hashes de départ :

    hash_bool
    clé => valeur
    foo => 0
    bar => 1
    truc => 1
    bidule => 0

    hash_datas, avec les mêmes clés..comporte les datas
    clé => valeur
    foo => "oh"
    bar => "super"
    truc => "cool"
    bidule => "les hashes"

    Voilà ce dont j'ai besoin en résultat, disons dans hash_merge:
    clé => valeur
    bar => "super"
    truc => "cool"

    Mais je m'aperçois en même temps qu'il manque un "produit matriciel" dans ce que j'ai appelé "la premiere solution".

  4. #4
    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
    euh je ne saisi pas la logique de ton exemple

  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
    oup's, c'est ton clé => valeur qui m'a induit en erreur. Si j'ai bien compris, le principe est le suivant.

    Tu lis les 2 hashs et on ne travaille que sur les clés communes aux 2 hashs. Ensuite, on lit et ne récupère que les clés de hash_bool ayant en valeur 1. C'est ça ?

  6. #6
    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
    si oui, voici une solution
    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;
    use warnings;
    use Data::Dumper;
     
    my %hash_bool = (
      foo    => 0,
      bar    => 1,
      truc   => 1,
      bidule => 0,
    );
     
    my %hash_datas = (
      tutu   => 'oh',
      bar    => 'super',
      truc   => 'cool',
      bidule => 'les hashes',
    );
     
    my %hash_common = hash_merge( \%hash_bool, \%hash_datas );
     
    sub hash_merge {
      my ( $ref_boolean, $ref_data ) = @_;
     
      my %merge;
      foreach ( grep { $ref_boolean->{$_} and $ref_boolean->{$_} == 1 } keys %{$ref_data} ) {
        $merge{$_} = $ref_data->{$_};
      }
      return %merge;
    }

  7. #7
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2011
    Messages
    184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 184
    Par défaut
    C'est ce que fait mon code (en théorie).
    Du moins, il renvoie :
    bar => "super"
    truc => "cool"

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

Discussions similaires

  1. fusion de table avec un champ en commun
    Par chamoix dans le forum Access
    Réponses: 3
    Dernier message: 13/12/2006, 23h18
  2. [MySQL] Requete sur 2 tables avec champs commun
    Par marcd dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 20/04/2006, 16h14
  3. location.hash avec Safari et Konqueror
    Par wrmmv dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 06/10/2005, 13h59
  4. Perdu avec la communication avec le port serie
    Par gilles641 dans le forum Langage
    Réponses: 8
    Dernier message: 23/08/2005, 20h11

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