Hash "réciproque" d'une liste

Le
Eric C.
Bonjour à tous (ça ne me rajeunit pas, la dernière fois que j'ai post=
é
dans ce groupe, d'après Google, c'était en avril 2001 ), j'ai une
question plus "esthétique" qu'autre chose : comment construire le plus
simplement possible le hash "réciproque" d'une liste ? Si la liste
associe des valeurs aux indices, ce hash doit associer les indices aux
valeurs. Petit exemple pour illustrer :
@tab=("a","b","c","d");
$length=@tab;
for ($i=0;$i<$length;$i++) {
$my_hash{$tab[$i]}=$i;
}
J'imagine que ça doit pouvoir s'écrire en une ligne, mais je n'ai rien
trouvé


Eric
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Paul Gaborit
Le #22198401
À (at) Tue, 1 Jun 2010 05:59:09 -0700 (PDT),
"Eric C."
Bonjour à tous (ça ne me rajeunit pas, la dernière fois que j'ai posté
dans ce groupe, d'après Google, c'était en avril 2001 ...),



Bonjour,

j'ai une
question plus "esthétique" qu'autre chose : comment construire le plus
simplement possible le hash "réciproque" d'une liste ? Si la liste
associe des valeurs aux indices, ce hash doit associer les indices aux
valeurs. Petit exemple pour illustrer :
@tab=("a","b","c","d");
$length=@tab;
for ($i=0;$i<$length;$i++) {
$my_hash{$tab[$i]}=$i;
}
J'imagine que ça doit pouvoir s'écrire en une ligne, mais je n'ai rien
trouvé ...



En supposant que les valeurs sont uniques (bijection indice <-> valeur)
alors votre code est correct. On peut l'écrire de manière un tout petit
peu plus "perlienne" (mais pas obligatoirement plus efficace -- il
faudrait faire un benchmark) :

my @tab = "a" .. "z";
my %my_hash = map {($tab[$_] => $_)} 0..$#tab;

--
Paul Gaborit - Perl en français -
Eric C.
Le #22206411
On 1 juin, 15:18, Paul Gaborit


En supposant que les valeurs sont uniques (bijection indice <-> valeur)
alors votre code est correct. On peut l' crire de mani re un tout petit
peu plus "perlienne" (mais pas obligatoirement plus efficace -- il
faudrait faire un benchmark) :

  my @tab = "a" .. "z";
  my %my_hash = map {($tab[$_] => $_)} 0..$#tab;



Merci, je me doutais qu'il y avait une solution par map, mais mon perl
étant un peu rouillé ça n'était pas (re)venu.
Niveau lisibilité, difficile de dire quelle solution est la plus
compréhensible ...
Je n'avais effectivement pas pensé à une éventuelle non-bijectivité
(je n'ai pas ce problème, les valeurs sont des noms de colonnes
obligatoirement différents).

En tout cas je constate que les mêmes anges gardiens veillent encore
et toujours sur le ng :)

Eric
Jerome Quelin
Le #22207671
Paul Gaborit wrote:
J'imagine que ça doit pouvoir s'écrire en une ligne, mais je n'ai rien
trouvé ...



En supposant que les valeurs sont uniques (bijection indice <-> valeur)
alors votre code est correct. On peut l'écrire de manière un tout petit
peu plus "perlienne" (mais pas obligatoirement plus efficace -- il
faudrait faire un benchmark) :

my @tab = "a" .. "z";
my %my_hash = map {($tab[$_] => $_)} 0..$#tab;



ou en utilisant des tranches de hash :
my %hash;
@hash{ @tab } = 0..$#tab;

jérôme
--

Paul Gaborit
Le #22207931
À (at) Thu, 03 Jun 2010 17:03:18 +0200,
Jerome Quelin
Paul Gaborit wrote:
J'imagine que ça doit pouvoir s'écrire en une ligne, mais je n'ai rien
trouvé ...



En supposant que les valeurs sont uniques (bijection indice <-> valeur)
alors votre code est correct. On peut l'écrire de manière un tout petit
peu plus "perlienne" (mais pas obligatoirement plus efficace -- il
faudrait faire un benchmark) :

my @tab = "a" .. "z";
my %my_hash = map {($tab[$_] => $_)} 0..$#tab;



ou en utilisant des tranches de hash :
my %hash;
@hash{ @tab } = 0..$#tab;



J'ai fait un petit benchmark pour voir et le résultat est sans appel :

Benchmark: timing 500000 iterations of foreach, map, slice...
foreach: 9.46806 wallclock secs ( 8.67 usr + 0.04 sys = 8.71 CPU)
@ 57405.28/s (nP0000)
map: 13.4544 wallclock secs (12.75 usr + 0.03 sys = 12.78 CPU)
@ 39123.63/s (nP0000)
slice: 6.38025 wallclock secs ( 6.05 usr + 0.02 sys = 6.07 CPU)
@ 82372.32/s (nP0000)

Il vaut donc mieux passer par les tranches de hash !

Pour ceux que ça intéresse, voici le code du benchmark :
############################
use Benchmark qw(:hireswallclock);

my @tab = "a" .. "z";

timethese(500000,
{
'map' => sub {
my %my_hash = map {($tab[$_] => $_)} 0..$#tab;
},
'foreach' => sub {
my %hash;
foreach (0..$#tab) {
$hash{$tab[$_]} = $_;
}
},
'slice' => sub {
my %hash;
@hash{ @tab } = 0..$#tab;
},
}
);
############################


--
Paul Gaborit - Perl en français -
Publicité
Poster une réponse
Anonyme