Hash de hashs : existence d'une clé dans une hash fille
8 réponses
vigi98
Bonjour,
J'ai une hash de hashs, disons =E7a (je l'ai copi=E9 sur un site):
my %file_attachments =3D (
'test1.zip' =3D> { '123'=3D>'yes','price' =3D> '10.00', 'desc'
=3D> 'the 1st test'},
'test2.zip' =3D> { 'price' =3D> '12.00', 'desc' =3D> 'the 2nd
test'},
'test3.zip' =3D> { 'price' =3D> '13.00', 'desc' =3D> 'the 3rd
test'},
'test4.zip' =3D> { 'price' =3D> '14.00', 'desc' =3D> 'the 4th
test'}
);
Je sais que je peux retrouver les =E9l=E9ments via les cl=E9s de la hash
m=E8re comme ceci:
if ( exists($file_attachments{$file})){
$price=3D$file_attachments{$file}->{'price'};
etc...
}
Mais si je veux retrouver des =E9l=E9ments via une cl=E9 d'une hash fille,
comment fais-je (sans faire de boucle, bien s=FBr) ? Par exemple, si je
veux retrouver la hash contenant la cl=E9 123, y a-t-il un moyen ? Un
truc du genre :
if ( exists($file_attachments{*}{'123'})){...
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Jacques Caron
Salut,
On 13 Jun 2005 07:20:22 -0700, wrote:
Mais si je veux retrouver des éléments via une clé d'une hash fille, comment fais-je (sans faire de boucle, bien sûr) ? Par exemple, si je veux retrouver la hash contenant la clé 123, y a-t-il un moyen ? Un truc du genre : if ( exists($file_attachments{*}{'123'})){...
Ce n'est pas possible. Deux solutions: - inverser les deux niveaux de hash - utiliser une boucle éventuellement fortement "inlinée" genre if (scalar (grep {exists{$_->{123}} values %file_attachments)>0)... (non testé, mais ça doit pas être loin). Mais la performance n'est pas vraiment la même.
Jacques.
Salut,
On 13 Jun 2005 07:20:22 -0700, <vigi98@free.fr> wrote:
Mais si je veux retrouver des éléments via une clé d'une hash fille,
comment fais-je (sans faire de boucle, bien sûr) ? Par exemple, si je
veux retrouver la hash contenant la clé 123, y a-t-il un moyen ? Un
truc du genre :
if ( exists($file_attachments{*}{'123'})){...
Ce n'est pas possible. Deux solutions:
- inverser les deux niveaux de hash
- utiliser une boucle éventuellement fortement "inlinée" genre if (scalar
(grep {exists{$_->{123}} values %file_attachments)>0)... (non testé, mais
ça doit pas être loin). Mais la performance n'est pas vraiment la même.
Mais si je veux retrouver des éléments via une clé d'une hash fille, comment fais-je (sans faire de boucle, bien sûr) ? Par exemple, si je veux retrouver la hash contenant la clé 123, y a-t-il un moyen ? Un truc du genre : if ( exists($file_attachments{*}{'123'})){...
Ce n'est pas possible. Deux solutions: - inverser les deux niveaux de hash - utiliser une boucle éventuellement fortement "inlinée" genre if (scalar (grep {exists{$_->{123}} values %file_attachments)>0)... (non testé, mais ça doit pas être loin). Mais la performance n'est pas vraiment la même.
Jacques.
Paul Gaborit
À (at) 13 Jun 2005 07:20:22 -0700, écrivait (wrote):
Mais si je veux retrouver des éléments via une clé d'une hash fille, comment fais-je (sans faire de boucle, bien sûr) ? Par exemple, si je veux retrouver la hash contenant la clé 123, y a-t-il un moyen ? Un truc du genre : if ( exists($file_attachments{*}{'123'})){...
Le problème est qu'il peut exister 0, une ou plusieurs clés qui répondent à votre critére. Les fonctions 'exists' et 'defined' ne fonctionnent que pour un objet bien précis.
Dans votre cas, il faut faire une recherche des clés :
my @keys_ok grep {defined $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la table de hachage anonyme associée contient une clé '123' liée à une valeur définie.
my @keys_ok grep {exists $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la table de hachage anonyme associée contient une clé '123'.
Mais tout cela ne sera pas obligatoirement efficace...
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>
À (at) 13 Jun 2005 07:20:22 -0700,
vigi98@free.fr écrivait (wrote):
Mais si je veux retrouver des éléments via une clé d'une hash fille,
comment fais-je (sans faire de boucle, bien sûr) ? Par exemple, si je
veux retrouver la hash contenant la clé 123, y a-t-il un moyen ? Un
truc du genre :
if ( exists($file_attachments{*}{'123'})){...
Le problème est qu'il peut exister 0, une ou plusieurs clés qui répondent à
votre critére. Les fonctions 'exists' et 'defined' ne fonctionnent que pour un
objet bien précis.
Dans votre cas, il faut faire une recherche des clés :
my @keys_ok grep {defined $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la
table de hachage anonyme associée contient une clé '123' liée à une valeur
définie.
my @keys_ok grep {exists $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la
table de hachage anonyme associée contient une clé '123'.
Mais tout cela ne sera pas obligatoirement efficace...
--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>
À (at) 13 Jun 2005 07:20:22 -0700, écrivait (wrote):
Mais si je veux retrouver des éléments via une clé d'une hash fille, comment fais-je (sans faire de boucle, bien sûr) ? Par exemple, si je veux retrouver la hash contenant la clé 123, y a-t-il un moyen ? Un truc du genre : if ( exists($file_attachments{*}{'123'})){...
Le problème est qu'il peut exister 0, une ou plusieurs clés qui répondent à votre critére. Les fonctions 'exists' et 'defined' ne fonctionnent que pour un objet bien précis.
Dans votre cas, il faut faire une recherche des clés :
my @keys_ok grep {defined $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la table de hachage anonyme associée contient une clé '123' liée à une valeur définie.
my @keys_ok grep {exists $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la table de hachage anonyme associée contient une clé '123'.
Mais tout cela ne sera pas obligatoirement efficace...
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>
vigi98
"Paul Gaborit" a écrit dans le message de news:
À (at) 13 Jun 2005 07:20:22 -0700, écrivait (wrote):
Mais si je veux retrouver des éléments via une clé d'une hash fille, comment fais-je (sans faire de boucle, bien sûr) ? Par exemple, si je veux retrouver la hash contenant la clé 123, y a-t-il un moyen ? Un truc du genre : if ( exists($file_attachments{*}{'123'})){...
Le problème est qu'il peut exister 0, une ou plusieurs clés qui répondent à votre critére. Les fonctions 'exists' et 'defined' ne fonctionnent que pour un objet bien précis.
Dans votre cas, il faut faire une recherche des clés :
my @keys_ok > grep {defined $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la table de hachage anonyme associée contient une clé '123' liée à une valeur définie.
my @keys_ok > grep {exists $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la table de hachage anonyme associée contient une clé '123'.
Mais tout cela ne sera pas obligatoirement efficace...
Je ne sais pas si c'est efficace, mais c'est élégant. A tel point que je ne
comprends pas très bien le syntaxe, d'ailleurs. Le $_ vient du "keys %file_attachments" ? Et du coup, en une seule ligne, sans boucle, on parcourt toute la table ? C'est beau.
"Paul Gaborit" <Paul.Gaborit@invalid.invalid> a écrit dans le message de
news: r7aclujo1o.fsf@vaugirard.enstimac.fr...
À (at) 13 Jun 2005 07:20:22 -0700,
vigi98@free.fr écrivait (wrote):
Mais si je veux retrouver des éléments via une clé d'une hash fille,
comment fais-je (sans faire de boucle, bien sûr) ? Par exemple, si je
veux retrouver la hash contenant la clé 123, y a-t-il un moyen ? Un
truc du genre :
if ( exists($file_attachments{*}{'123'})){...
Le problème est qu'il peut exister 0, une ou plusieurs clés qui répondent
à
votre critére. Les fonctions 'exists' et 'defined' ne fonctionnent que
pour un
objet bien précis.
Dans votre cas, il faut faire une recherche des clés :
my @keys_ok > grep {defined $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour
lesquelles la
table de hachage anonyme associée contient une clé '123' liée à une valeur
définie.
my @keys_ok > grep {exists $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour
lesquelles la
table de hachage anonyme associée contient une clé '123'.
Mais tout cela ne sera pas obligatoirement efficace...
Je ne sais pas si c'est efficace, mais c'est élégant. A tel point que je ne
comprends pas très bien le syntaxe, d'ailleurs. Le $_ vient du "keys
%file_attachments" ? Et du coup, en une seule ligne, sans boucle, on
parcourt toute la table ? C'est beau.
À (at) 13 Jun 2005 07:20:22 -0700, écrivait (wrote):
Mais si je veux retrouver des éléments via une clé d'une hash fille, comment fais-je (sans faire de boucle, bien sûr) ? Par exemple, si je veux retrouver la hash contenant la clé 123, y a-t-il un moyen ? Un truc du genre : if ( exists($file_attachments{*}{'123'})){...
Le problème est qu'il peut exister 0, une ou plusieurs clés qui répondent à votre critére. Les fonctions 'exists' et 'defined' ne fonctionnent que pour un objet bien précis.
Dans votre cas, il faut faire une recherche des clés :
my @keys_ok > grep {defined $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la table de hachage anonyme associée contient une clé '123' liée à une valeur définie.
my @keys_ok > grep {exists $file_attachments{$_}{123}} keys %file_attachments;
Dans @keys_ok vous retrouverez la liste de clés principales pour lesquelles la table de hachage anonyme associée contient une clé '123'.
Mais tout cela ne sera pas obligatoirement efficace...
Je ne sais pas si c'est efficace, mais c'est élégant. A tel point que je ne
comprends pas très bien le syntaxe, d'ailleurs. Le $_ vient du "keys %file_attachments" ? Et du coup, en une seule ligne, sans boucle, on parcourt toute la table ? C'est beau.
vigi98
Ce n'est pas possible. Deux solutions: - inverser les deux niveaux de hash - utiliser une boucle éventuellement fortement "inlinée" genre if (scalar (grep {exists{$_->{123}} values %file_attachments)>0)... (non testé, mais ça doit pas être loin). Mais la performance n'est pas vraiment la même.
Jacques.
Par boucle inlinée, vous entendez que par cette seule ligne, toute la table est parcourue ? Au niveau performance, n'est-ce pas equivalent à un for ? En tous cas, merci beaucoup pour le truc. Je vais l'essayer.
Ce n'est pas possible. Deux solutions:
- inverser les deux niveaux de hash
- utiliser une boucle éventuellement fortement "inlinée" genre if (scalar
(grep {exists{$_->{123}} values %file_attachments)>0)... (non testé, mais
ça doit pas être loin). Mais la performance n'est pas vraiment la même.
Jacques.
Par boucle inlinée, vous entendez que par cette seule ligne, toute la table
est parcourue ? Au niveau performance, n'est-ce pas equivalent à un for ?
En tous cas, merci beaucoup pour le truc. Je vais l'essayer.
Ce n'est pas possible. Deux solutions: - inverser les deux niveaux de hash - utiliser une boucle éventuellement fortement "inlinée" genre if (scalar (grep {exists{$_->{123}} values %file_attachments)>0)... (non testé, mais ça doit pas être loin). Mais la performance n'est pas vraiment la même.
Jacques.
Par boucle inlinée, vous entendez que par cette seule ligne, toute la table est parcourue ? Au niveau performance, n'est-ce pas equivalent à un for ? En tous cas, merci beaucoup pour le truc. Je vais l'essayer.
Jacques Caron
Salut,
On Tue, 14 Jun 2005 21:26:55 +0200, vigi98 wrote:
Par boucle inlinée, vous entendez que par cette seule ligne, toute la table est parcourue ?
Oui.
Au niveau performance, n'est-ce pas equivalent à un for ?
Si, totalement. Clairement pas aussi efficace qu'un lookup unique dans un hash...
Jacques.
Salut,
On Tue, 14 Jun 2005 21:26:55 +0200, vigi98 <vigi98@free.fr> wrote:
Par boucle inlinée, vous entendez que par cette seule ligne, toute la
table est parcourue ?
Oui.
Au niveau performance, n'est-ce pas equivalent à un for ?
Si, totalement. Clairement pas aussi efficace qu'un lookup unique dans un
hash...
Par boucle inlinée, vous entendez que par cette seule ligne, toute la table est parcourue ?
Oui.
Au niveau performance, n'est-ce pas equivalent à un for ?
Si, totalement. Clairement pas aussi efficace qu'un lookup unique dans un hash...
Jacques.
Jacques Caron
Salut,
On Tue, 14 Jun 2005 21:23:29 +0200, vigi98 wrote:
Je ne sais pas si c'est efficace, mais c'est élégant. A tel point que je ne comprends pas très bien le syntaxe, d'ailleurs. Le $_ vient du "keys %file_attachments" ? Et du coup, en une seule ligne, sans boucle, on parcourt toute la table ? C'est beau.
$_ est une variable qui est utilisée à chaque fois qu'il y a une variable de boucle implicite. C'est valable aussi bien pour:
while (<DESRIPTEUR>) { ... }
for (@liste) { ... }
grep { ... } @liste
map { ... } @liste
Et probablement quelques autres.
L'intérêt c'est qu'il y a aussi beaucoup de structures qui utilisent $_ implicitement si rien d'autre n'est précisé. C'est le cas des opérateurs de regex, par exemple, mais aussi de chop ou chomp, de split, de print, et tout plein d'autres.
Dans le cas présent (grep ou map), $_ va prendre successivement chacune des valeurs de la liste fournie après le bloc. D'ailleurs ici on peut aussi faire:
grep {defined $_->{123}} values %hash
Jacques.
Salut,
On Tue, 14 Jun 2005 21:23:29 +0200, vigi98 <vigi98@free.fr> wrote:
Je ne sais pas si c'est efficace, mais c'est élégant. A tel point que je
ne comprends pas très bien le syntaxe, d'ailleurs. Le $_ vient du "keys
%file_attachments" ? Et du coup, en une seule ligne, sans boucle, on
parcourt toute la table ? C'est beau.
$_ est une variable qui est utilisée à chaque fois qu'il y a une variable
de boucle implicite. C'est valable aussi bien pour:
while (<DESRIPTEUR>)
{
...
}
for (@liste)
{
...
}
grep { ... } @liste
map { ... } @liste
Et probablement quelques autres.
L'intérêt c'est qu'il y a aussi beaucoup de structures qui utilisent $_
implicitement si rien d'autre n'est précisé. C'est le cas des opérateurs
de regex, par exemple, mais aussi de chop ou chomp, de split, de print, et
tout plein d'autres.
Dans le cas présent (grep ou map), $_ va prendre successivement chacune
des valeurs de la liste fournie après le bloc. D'ailleurs ici on peut
aussi faire:
Je ne sais pas si c'est efficace, mais c'est élégant. A tel point que je ne comprends pas très bien le syntaxe, d'ailleurs. Le $_ vient du "keys %file_attachments" ? Et du coup, en une seule ligne, sans boucle, on parcourt toute la table ? C'est beau.
$_ est une variable qui est utilisée à chaque fois qu'il y a une variable de boucle implicite. C'est valable aussi bien pour:
while (<DESRIPTEUR>) { ... }
for (@liste) { ... }
grep { ... } @liste
map { ... } @liste
Et probablement quelques autres.
L'intérêt c'est qu'il y a aussi beaucoup de structures qui utilisent $_ implicitement si rien d'autre n'est précisé. C'est le cas des opérateurs de regex, par exemple, mais aussi de chop ou chomp, de split, de print, et tout plein d'autres.
Dans le cas présent (grep ou map), $_ va prendre successivement chacune des valeurs de la liste fournie après le bloc. D'ailleurs ici on peut aussi faire:
grep {defined $_->{123}} values %hash
Jacques.
Paul Gaborit
À (at) Wed, 15 Jun 2005 00:18:20 +0200, "Jacques Caron" écrivait (wrote):
Dans le cas présent (grep ou map), $_ va prendre successivement chacune des valeurs de la liste fournie après le bloc. D'ailleurs ici on peut aussi faire:
grep {defined $_->{123}} values %hash
Ce n'est pas exactement la même chose puisque ici on renvoie une liste de références à des tables de hachage anonymes définissant la clé '123'. On ne sait plus à quelle clé était rattachée chacune de ces tables dans la table d'origine (%hash).
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>
À (at) Wed, 15 Jun 2005 00:18:20 +0200,
"Jacques Caron" <jc@oxado.com> écrivait (wrote):
Dans le cas présent (grep ou map), $_ va prendre successivement chacune des
valeurs de la liste fournie après le bloc. D'ailleurs ici on peut aussi
faire:
grep {defined $_->{123}} values %hash
Ce n'est pas exactement la même chose puisque ici on renvoie une liste de
références à des tables de hachage anonymes définissant la clé '123'. On ne
sait plus à quelle clé était rattachée chacune de ces tables dans la table
d'origine (%hash).
--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>
À (at) Wed, 15 Jun 2005 00:18:20 +0200, "Jacques Caron" écrivait (wrote):
Dans le cas présent (grep ou map), $_ va prendre successivement chacune des valeurs de la liste fournie après le bloc. D'ailleurs ici on peut aussi faire:
grep {defined $_->{123}} values %hash
Ce n'est pas exactement la même chose puisque ici on renvoie une liste de références à des tables de hachage anonymes définissant la clé '123'. On ne sait plus à quelle clé était rattachée chacune de ces tables dans la table d'origine (%hash).
-- Paul Gaborit - <http://perso.enstimac.fr/~gaborit/> Perl en français - <http://perl.enstimac.fr/>
Jacques Caron
On Wed, 15 Jun 2005 09:50:44 +0200, Paul Gaborit wrote:
Ce n'est pas exactement la même chose puisque ici on renvoie une liste de références à des tables de hachage anonymes définissant la clé '123'. On ne sait plus à quelle clé était rattachée chacune de ces tables dans la table d'origine (%hash).
Oui, mais comme le but du jeu original était (il me semble) juste de savoir s'il y avait ou pas de telles clefs, ça devrait suffire. A adapter en fonction du contexte, bien sûr.
Jacques.
On Wed, 15 Jun 2005 09:50:44 +0200, Paul Gaborit
<Paul.Gaborit@invalid.invalid> wrote:
Ce n'est pas exactement la même chose puisque ici on renvoie une liste de
références à des tables de hachage anonymes définissant la clé '123'. On
ne sait plus à quelle clé était rattachée chacune de ces tables dans la
table d'origine (%hash).
Oui, mais comme le but du jeu original était (il me semble) juste de
savoir s'il y avait ou pas de telles clefs, ça devrait suffire. A adapter
en fonction du contexte, bien sûr.
On Wed, 15 Jun 2005 09:50:44 +0200, Paul Gaborit wrote:
Ce n'est pas exactement la même chose puisque ici on renvoie une liste de références à des tables de hachage anonymes définissant la clé '123'. On ne sait plus à quelle clé était rattachée chacune de ces tables dans la table d'origine (%hash).
Oui, mais comme le but du jeu original était (il me semble) juste de savoir s'il y avait ou pas de telles clefs, ça devrait suffire. A adapter en fonction du contexte, bien sûr.