OVH Cloud OVH Cloud

Nommer un hachage par une variable scalaire

6 réponses
Avatar
Patrice Karatchentzeff
Salut,

Le titre n'est pas forcément explicite...

J'ai un fichier se présentant sous la forme :

Nom Prénom info1 info2 (pour simplifier)

et je désire créer un hachage du genre

%Nom = (
Name => "Nom",
surname => "Prénom",
inf1 => "info1",
inf2 => "info2",
)

Jusqu'à là, pas de soucis...

Je ne veux pas entrer à la main tous les hachages : pour cela, je crée
un tableau contenant la liste des noms du fichier et je désire me
servir de ce tableau pour créer les-dit hachages...

Voici ce que j'ai (mal) pondu

sub effectif
{
my ($file) = @_; # reçoit le fameux fichier
my (@effectif, @field);
open(EFFECTIF,$file) || die "Impossible d'ouvrir le fichier $file : $!\n";
while(<EFFECTIF>)
{
@field=split();
push(@effectif, $field[0]); # remplit le fameux tableau
my %$field[0] = ""; # déclaration pour le pragma use
%$field[0] =
(nom => "$effectif[0]",
prenom => "$effectif[1]",
grade => "$effectif[2]",
matricule => "$effectif[3]",
);
};
close(EFFECTIF);
return (@effectif);
};


Bon, cela ne fonctionne pas... Comment écrire %Nom en faisant
référence au bon scalaire du tableau ? J'ai essayé plusieurs trucs
sans y arriver...

Sinon, un deuxième point : lorsque l'on use le pragma strict, on est
obligé de déclarer les variables... J'ai ici un double problème :
comment déclarer ma nouvelle variable de hachage dans ce cas (création
dynamique) et comment la rendre globale (pour cela, encore, je crois
voir : il suffit de la retourner en fin de sous-programme mais cela
sous-entend de les déclarer en en-tête... alors que je ne connais pas
encore leur nom).

Merci : je sais, c'est un peu tordu mais c'est pour cela que j'utilise
Perl ;-)

PK

--
      |\      _,,,---,,_       Patrice KARATCHENTZEFF
ZZZzz /,`.-'`'    -.  ;-;;,_   mailto:p.karatchentzeff@free.fr
     |,4-  ) )-,_. ,\ (  `'-'  http://p.karatchentzeff.free.fr
    '---''(_/--'  `-'\_)       

6 réponses

Avatar
Jedaï
Patrice Karatchentzeff wrote:
Salut,

Le titre n'est pas forcément explicite...

J'ai un fichier se présentant sous la forme :

Nom Prénom info1 info2 (pour simplifier)

et je désire créer un hachage du genre

%Nom = (
Name => "Nom",
surname => "Prénom",
inf1 => "info1",
inf2 => "info2",
)

Jusqu'à là, pas de soucis...

Je ne veux pas entrer à la main tous les hachages : pour cela, je crée
un tableau contenant la liste des noms du fichier et je désire me
servir de ce tableau pour créer les-dit hachages...

Voici ce que j'ai (mal) pondu

sub effectif
{
my ($file) = @_; # reçoit le fameux fichier
my (@effectif, @field);
open(EFFECTIF,$file) || die "Impossible d'ouvrir le fichier $file : $!n";
while(<EFFECTIF>)
{
@field=split();
push(@effectif, $field[0]); # remplit le fameux tableau
my %$field[0] = ""; # déclaration pour le pragma use
%$field[0] > (nom => "$effectif[0]",
prenom => "$effectif[1]",
grade => "$effectif[2]",
matricule => "$effectif[3]",
);
};
close(EFFECTIF);
return (@effectif);
};


Bon, cela ne fonctionne pas... Comment écrire %Nom en faisant
référence au bon scalaire du tableau ? J'ai essayé plusieurs trucs
sans y arriver...

Sinon, un deuxième point : lorsque l'on use le pragma strict, on est
obligé de déclarer les variables... J'ai ici un double problème :
comment déclarer ma nouvelle variable de hachage dans ce cas (création
dynamique) et comment la rendre globale (pour cela, encore, je crois
voir : il suffit de la retourner en fin de sous-programme mais cela
sous-entend de les déclarer en en-tête... alors que je ne connais pas
encore leur nom).

Merci : je sais, c'est un peu tordu mais c'est pour cela que j'utilise
Perl ;-)

PK



Pour faire ce que tu semble vouloir faire, je te conseille plutôt un
tableau de hachage :
@effectif = ( {
Name => "Nom1",
surname => "Prénom1",
inf1 => "info11",
inf2 => "info21",
},
{
Name => "Nom2",
surname => "Prénom2",
inf1 => "info12",
inf2 => "info22",
}, .... );

Très simple à réaliser :

#!perl

sub effectif {
my $file = shift; # reçoit le fameux fichier
my (@effectif, @field);
open EFFECTIF, '<:raw', $file
or die "Impossible d'ouvrir le fichier $file : $!n";

while(<EFFECTIF>) {

@field=split;
my %personne = (nom => $field[0],
prenom => $field[1],
grade => $field[2],
matricule => $field[3],
);
push(@effectif, %personne); # remplit le fameux tableau

}

close EFFECTIF;
return @effectif;
}

__END__

Si tu veux un tableau avec juste les noms, il te suffit de faire :
my @noms = grep { $_->{nom} } @effectif;

Voir perlref pour une meilleure explication. :)

--
Jedaï

Avatar
Laurent Wacrenier
Patrice Karatchentzeff écrit:
Je ne veux pas entrer à la main tous les hachages : pour cela, je crée
un tableau contenant la liste des noms du fichier et je désire me
servir de ce tableau pour créer les-dit hachages...

Voici ce que j'ai (mal) pondu


Tu veux un tableau de références de hash ?
Essaye quelque chose comme ça :

my @field;
while(<EFFECTIF>) {
my @e = split();
push @field, {
nom => shift @e,
prenom => shift @e,
inf1 => shift @e,
inf2 => shift @e,
};
}

Pour lire les noms :

print $_->{nom}, "n" for (@field);

Avatar
Laurent Wacrenier
Jedaï écrit:
my @noms = grep { $_->{nom} } @effectif;


c'est la liste des référence de hash dont l'enregistrement 'nom' est vrai.

s/grep/map/;

Avatar
Patrice Karatchentzeff
Jedaï writes:

[...]

sub effectif {
my $file = shift; # reçoit le fameux fichier
my (@effectif, @field);
open EFFECTIF, '<:raw', $file
or die "Impossible d'ouvrir le fichier $file : $!n";

while(<EFFECTIF>) {

@field=split;
my %personne = (nom => $field[0],
prenom => $field[1],
grade => $field[2],
matricule => $field[3],
);
push(@effectif, %personne); # remplit le fameux tableau

}

close EFFECTIF;
return @effectif;
}

__END__


Effectivement, cela résout au moins mon problème...

Merci

Par contre, la question reste toujours posée... au moins pour ma
culture personnelle.

Quid du nommage du scalaire dans le hash ? Et quid du pragma ?

PK

--
      |      _,,,---,,_       Patrice KARATCHENTZEFF
ZZZzz /,`.-'`'    -.  ;-;;,_   mailto:
     |,4-  ) )-,_. , (  `'-'  http://p.karatchentzeff.free.fr
    '---''(_/--'  `-'_)       

Avatar
Jedaï
Laurent Wacrenier wrote:
Jedaï écrit:

my @noms = grep { $_->{nom} } @effectif;



c'est la liste des référence de hash dont l'enregistrement 'nom' est vrai.

s/grep/map/;


Oups, j'ai eu un moment d'égarement (après quelques excellentes
bouteilles et à 23h...) ;)

Pour me faire pardonner, voici un code pour trier le tableau obtenu :
#dans l'ordre alphabétique d'abord par nom puis par prénom :
{
use locale; #pour classer 'é' comme 'e'
@effectif = sort { $a->{nom} cmp $b->{nom} or $a->prenom} cmp
$b->{prenom} } @effectif;
}

Par ailleurs je ne suis pas sûr de comprendre ce que veux dire :
Quid du nommage du scalaire dans le hash ?
?



Pour déclarer une variable globale, il faut utiliser our au lieu de my,
mais je ne pense pas que ce soit recommandé pour ce genre d'usage, mieux
vaut utiliser les paramêtres et les valeurs de retour. :)

--
Jedaï


Avatar
Jedaï
Jean-Louis MOREL wrote:

Dans l'article , p.
a dit...

Effectivement, cela résout au moins mon problème...

Merci

Par contre, la question reste toujours posée... au moins pour ma
culture personnelle.

Quid du nommage du scalaire dans le hash ? Et quid du pragma ?




Si j'ai bien compris la question, vous voulez utiliser des références
symboliques : vous avez un scalaire $field[0] qui contient 'Dupont' et vous
voulez faire un hash %Dupont. Il suffit de faire %{$field[0]} = (...) Votre
code initial était presque bon, mais vous utilisez %$field[0] et comme %
a priorité sur [ ], vous avez le message d'erreur : <Global symbol "$field"
requires explicit package name...>
D'autre part, le hash ainsi créé est global (il est dans la table des
symboles du package courant), vous ne pouvez pas le rendre lexical avec my.
Evidemment, avec un 'use strict', Perl va râler : il faut autoriser les
références symboliques avec no strict 'refs'; Voir perlref :
http://www.bribes.org/perl/docfr/perlref.html#LE2B14E0D

Ceci dit, l'usage des références symboliques est fortement déconseillé.
Voir : http://perl.plover.com/varvarname.html

Votre bout de programme modifié et testé :

#!/usr/bin/perl -w
use strict;
no strict 'refs'; # autorise les références symboliques

sub effectif
{
my ($file) = @_; # reçoit le fameux fichier
my (@effectif, @field);
open(EFFECTIF,$file) || die "Impossible d'ouvrir le fichier $file : $!n";
while(<EFFECTIF>)
{
@field=split();
push @effectif, $field[0]; # remplit le fameux tableau
# my %$field[0] = ""; # déclaration pour le pragma use
%{$field[0]} > (nom => "$field[0]",
prenom => "$field[1]",
grade => "$field[2]",
matricule => "$field[3]",
);
};
close(EFFECTIF);
return (@effectif);
};

foreach ( effectif('effectif.txt') ) {
print "$$_{prenom} $$_{nom}n";
}

__END__




L'usage de référence symbolique ici est encore plus dangereux
qu'ailleurs : supposons (et ce n'est pas une supposition déraisonnable)
que plusieurs des personnes de l'effectif ait le même nom, la dernière
effacerait les autres..:(

--
Jedaï