recherche algo pour expansion d'une structure.

recherche algo pour expansion d'une structure. - Perl - Programmation

Marsh Posté le 04-02-2005 à 20:15:12    

Salut,
 
j'ai une structure de type HoHoHoH... de profondeur inconnue, exemple:
 

Code :
  1. $toto = {
  2.            key1 => {
  3.               key2 => {
  4.                  param1 => value1,
  5.                  param2 => value2,
  6.                  },
  7.               * => {
  8.                  param3 => value3,
  9.                  },
  10.               },
  11.            * => {
  12.               key4 => {
  13.                  * => {
  14.                     param4 => value4,
  15.                     },
  16.                  },
  17.               },
  18.            };


 
je cherche a reperer les cles egales a '*' et quand j'en trouve une,
je veut copier la structure sur laquelle pointe la cle un nombre X de fois en creeant les cles necessaires.
(on ne s'interessera pas ici a la facon de nommer les nouvelles cles crees)
 
puis la structure ayant pour cle '*' est supprime.
 
exemples
X est egale a 2:
 
je voudrais obtenir une structure egale a cela:
 

Code :
  1. $toto = {
  2.            key1 => {
  3.               key2 => {
  4.                  param1 => value1,
  5.                  param2 => value2,
  6.                  },
  7.               newkey3 => {
  8.                  param3 => value3,
  9.                  },
  10.               newkey4 => {
  11.                  param3 => value3,
  12.                  },
  13.               },
  14.            newkey1 => {
  15.               key4 => {
  16.                  newkey6 => {
  17.                     param4 => value4,
  18.                     },
  19.                  },
  20.                  newkey5 => {
  21.                     param4 => value4,
  22.                     },
  23.                  },
  24.               },
  25.            newkey2 => {
  26.               key4 => {
  27.                  newkey8 => {
  28.                     param4 => value4,
  29.                     },
  30.                  },
  31.                  newkey7 => {
  32.                     param4 => value4,
  33.                     },
  34.                  },
  35.               },
  36.            };


 
j'ai deja reussi a faire quelque chose qui marche mais je parcours le hash a "expander" dans le sens "normal",
et par consequent je suis oblige de repeter l appel a ma fonction plusieurs fois car quand je copie un bloc
dont la cle etait une etoile, il peut arriver que je duplique a nouveau des etoiles qui se trouverai
dans la sous-structure copier...
 
bref ca fonctionne mais c'est pas beau !
 
l'ideal serait de faire un parcours du hash en profondeur, dans le sens "inverse",
mais je n'y arrive pas de cette facon...
 
si quelqu'un a reussi a comprendre mes explications qui sont pas tres clair,
deja bravo,
et eventuellement si vous aviez une idee pour m'aidez, n'hesitez pas.
 
je vous remercie d'avance.

Reply

Marsh Posté le 04-02-2005 à 20:15:12   

Reply

Marsh Posté le 04-02-2005 à 23:45:18    

si tu pouvais nous mettre le code de ton algo déjà codé (ou une version simplifiée) ça serait bien car on pourrait t'aider à le transformer/ améliorer

Reply

Marsh Posté le 05-02-2005 à 12:10:35    

dreameddeath a écrit :

si tu pouvais nous mettre le code de ton algo déjà codé (ou une version simplifiée) ça serait bien car on pourrait t'aider à le transformer/ améliorer


 

Code :
  1. &depth($default, $user);
  2. &depth($default, $user);
  3. ...
  4. sub depth {
  5.    my ($default, $user) = @_;
  6.    foreach my $key (keys %{ $default }) {
  7.       if ($key eq '*') {
  8.          &copy($default, $user, $default->{$key});
  9.       }
  10.       if (ref($default->{$key}) eq 'HASH') {
  11.          &depth($default->{$key}, $user->{$key});
  12.       }
  13.    }
  14. }
  15. sub copy {
  16.    my ($default, $user, $sub) = @_;
  17.    foreach my $z (keys %{ $user }) {
  18.       # create structure if dont already exist
  19.       $default->{$z} = {} unless defined $default->{$z};
  20.       my %e = %{ merge($default->{$z}, $sub) };
  21.       $default->{$z} = \%e;
  22.    }
  23.    delete $default->{'*'};
  24. }


 
voici donc ma facon de proceder actuellement, la ref de hash "$user" est la uniquement pour savoir quelle sont les cles que je doit creer au moment de la copie.
 
mais avec cette methode, il faut que j'appelle ma fonction &depth plusieurs fois pour avoir l'expansion de toutes les '*'.
 
dans l'exemple que j'ai donne precedemment il faudrat par exemple que je l'apelle 2 fois.

Reply

Marsh Posté le 06-02-2005 à 13:57:48    

bah déjà pourquoi tu ne fais pas qqch du type dans copy, qui va transformer avant de merger

Code :
  1. sub copy {
  2. #...
  3. $default->{$z} = \%e;
  4. #fait le depth sur la structure nouvellement créé...
  5. &depth($default->{$z},$user->{$z});
  6. }


je pense que ça devrait marcher !

Reply

Marsh Posté le 06-02-2005 à 14:26:43    

dreameddeath a écrit :

bah déjà pourquoi tu ne fais pas qqch du type dans copy, qui va transformer avant de merger

Code :
  1. sub copy {
  2. #...
  3. $default->{$z} = \%e;
  4. #fait le depth sur la structure nouvellement créé...
  5. &depth($default->{$z},$user->{$z});
  6. }


je pense que ça devrait marcher !


 
effectivement ca fonctionne.
maintenant je suis pas sur que ca soit plus optimise que la premiere methode...
 
ca evite d'appeller plusieurs fois la fonction au debut, certes.
 
mais ca n'empeche pas que le fait de parcourir le hash dans ce sens multiplie le nombre d'etoile a chaque copie si dans la structure copiée il y avait aussi des etoiles...
 
tu n'as pas une idee pour faire la meme chose mais en parcourant la structure à partir des elements les plus profonds ?


Message édité par djtoz le 06-02-2005 à 14:34:35
Reply

Marsh Posté le 07-02-2005 à 15:12:20    

Je ne suis pas sûr de comprendre dans ce cas la fonction de la HASH %user. C'est a priori elle qui contient, de manière HIERARCHIQUE, les infos qui doivent remplacer les "*".
 
une question me viennent dans ce cas :
- est-ce que les valeurs que prennes les '*' dans une sous-structure dépendent de la valeur de '*' dans la stucture parent
Dans ton exemple :

Code :
  1. $toto = {
  2.            ...
  3.            * => {
  4.              key4 => {
  5.                 * => {
  6.                     param4 => value4,
  7.                     },
  8.                  },
  9.              },
  10.           };


est-ce que la valeur 1er * (avant key4) implique des valeurs spécifiques du * de la sous-structure ? Ceci, d'après ton algorithme, me semble être le cas...
 
Mais bon si tu veux faire les éléments les plus profonds d'abord, il suffit de faire :

Code :
  1. sub copy {
  2.    my ($default, $user, $sub) = @_;
  3.    #modification de sub
  4.    &depth($sub,$user->{// je ne vois pas quoi mettre//});
  5.    foreach my $z (keys %{ $user }) {
  6.       # create structure if dont already exist
  7.       $default->{$z} = {} unless defined $default->{$z};
  8.       my %e = %{ merge($default->{$z}, $sub) };
  9.       $default->{$z} = \%e;
  10.    }
  11.    delete $default->{'*'};
  12. }


et dans ce cas il transformera le $sub avant de faire les copies mais j'ai peur que cela ne donne pas le bon résultat (toutes les sous-structures seront identiques alors que ce ne semble pas être le souhait)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed