Problème de références

Le
JB
Bonjour,

Étant débutant en références PERL j'ai quelques soucis.

Mon programme explore un fichier xml de généalogie (gramps).
Je cherche à créer des rapports qui n'existent pas dans le programme de
base.
Dans le cas présent je cherche à créer un rapport qui liste les médias et
qui les utilise.

Dans un premier temps le programme recherche les médias présents dans le
fichier et crée un hash qui contient les informations
de chaque média.

Chaque enregistrement à la forme :

##################################################################
# handle # identifiant # nom du fichier # liste des utilisateurs #
##################################################################

Voici la procédure de création du hash

$handle,le numéro du média
$id , identifiant
$file, nom du fichier média
$note, note attachée au média

#####################################
# ajoute un élément au hash objects #
#####################################

sub add_object
{
my($handle,$id,$file,$note)=@_;
my @users=();
my $tab=[$id,$file,$note,@users];
$h_objects{$handle}=$tab;
}

Dans un deuxième temps, le programme explore le fichier par personne,
famille, évènement, lieu et entre-autre met à jour le hash des objets.

Voici la routine de mise à jour du hash, l'idée est d'ajouter un tableau
[type d'utilisateur, utilisateur] dans la liste des utilisateurs du médium.

####################################################
# ajoute un utilisateur a un objet du hash objects #
####################################################

$handle , numero du média
$type , type d'utilisateur (personne, famille, evenement, lieux)
$id , id de l'utilisateur

sub add_object_user
{
my($handle,$type,$id)=@_;
my $user=[$type,$id];
my $object=$h_objects{$handle};
print "Ajout de l'utilisateur $id type $type à l'objet $object->[1]";

my @users=@$object->[3];
print "Avant :";
print "@users ";
push(@users,$user);

print "Après :";
print "Utilisateurs: @users ";
}


C'est cette dernière routine qui ne fonctionne pas, la liste des
utilisateurs ne grandit pas.

Je suis à la recherche d'aide (sans frapper!!!).

Merci.
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 #20244631
À (at) Mon, 28 Sep 2009 16:01:34 +0200,
JB
Voici la procédure de création du hash

$handle,le numéro du média
$id , identifiant
$file, nom du fichier média
$note, note attachée au média

#####################################
# ajoute un élément au hash objects #
#####################################

sub add_object
{
my($handle,$id,$file,$note)=@_;
my @users=();
my $tab=[$id,$file,$note,@users];
$h_objects{$handle}=$tab;
}



En fait dans cette procédure @users ne sert strictement à rien.

Comment voulez-vous stocker les users ? À plat, à la suite du tableau
qui contient $id, $file et $note ? Ou comme un tableau dont la
référence serait à la suite de $id, $file et $note ?

J'ai supposé que c'était cette dernière solution que vous
souhaitiez...

Cette procédure pourrait dont s'écrire de manière plus perlienne :

sub add_object {
my ($handle, $id, $file, $note) = @_;
# on avertit si l'objet est déjà défini
warn "$handle is already defined in h_object !"
if defined $h_objects{$handle};
# on place les trois valeurs plus une référence à un
# tableau (vide) d'utilisateurs en les associant à la clé $handle
# dans %h_object
$h_objects{$handle} = [$id, $file, $note, []];
}


Dans un deuxième temps, le programme explore le fichier par personne,
famille, évènement, lieu et entre-autre met à jour le hash des objets.

Voici la routine de mise à jour du hash, l'idée est d'ajouter un tableau
[type d'utilisateur, utilisateur] dans la liste des utilisateurs du médium.

####################################################
# ajoute un utilisateur a un objet du hash objects #
####################################################

$handle , numero du média
$type , type d'utilisateur (personne, famille, evenement, lieux)
$id , id de l'utilisateur

sub add_object_user
{
my($handle,$type,$id)=@_;
my $user=[$type,$id];
my $object=$h_objects{$handle};
print "Ajout de l'utilisateur $id type $type à l'objet $object->[1]n";

my @users=@$object->[3];
print "Avant :n";
print "@users n";
push(@users,$user);

print "Après :n";
print "Utilisateurs: @users n";
}



On peut simplifier/corriger tout cela par (j'ai rajouté une fonction
de debug) :

sub show_array_type_id {
my $ref = shift;
warn "nb user : ", scalar(@ref), "n";
foreach my $user (@$ref) {
warn "ttype $user->[0], id $user->[1]n";
}
}

sub add_object_user {
my($handle,$type,$id)=@_;

warn "Ajout de l'utilisateur $id type $type à l'objet $h_objects{$handle}[1]n";

warn "Avantn";
show_array_type_id($h_objects{$handle}[3]);

push @{$h_objects{$handle}[3]}, [$type, $id];

warn "Aprèsn";
show_array_type_id($h_objects{$handle}[3]);
}

Dernière remarque : plutôt que d'utiliser des tableaux pour stocker
les différentes informations, j'utiliserais plutôt des tables de
hachages pour rendre les chose plus claires (sauf pour les 'users' qui
sont effectivement dans une liste).

Cela donnerait alors :

sub add_object {
my ($handle, $id, $file, $note) = @_;
warn "$handle already defined in %h_object !"
if defined $h_objects{$handle};
$h_objects{$handle} = {
id => $id,
file => $file,
note => $note,
users => [],
};
}


sub show_array_type_id {
my $ref = shift;
warn "nb users : ", scalar(@$ref), "n";
foreach my $user (@$ref) {
warn "ttype $user->{type}, id $user->{id}n";
}
}

sub add_object_user {
my($handle,$type,$id)=@_;

warn "Ajout de l'utilisateur $id type $type à l'objet $h_objects{$handle}{file}n";

warn "Avantn";
show_array_type_id($h_objects{$handle}{users});

push @{$h_objects{$handle}{users}}, {type => $type, id => $id};

warn "Aprèsn";
show_array_type_id($h_objects{$handle}{users});
}


PS: code pas du tout testé...

--
Paul Gaborit - Perl en français -
JB
Le #20245191
Paul Gaborit wrote:
Cette procédure pourrait dont s'écrire de manière plus perlienne :

sub add_object {
my ($handle, $id, $file, $note) = @_;
# on avertit si l'objet est déjà défini
warn "$handle is already defined in h_object !"
if defined $h_objects{$handle};
# on place les trois valeurs plus une référence à un
# tableau (vide) d'utilisateurs en les associant à la clé $handle
# dans %h_object
$h_objects{$handle} = [$id, $file, $note, []];
}

Dernière remarque : plutôt que d'utiliser des tableaux pour stocker
les différentes informations, j'utiliserais plutôt des tables de
hachages pour rendre les chose plus claires (sauf pour les 'users' qui
sont effectivement dans une liste).

Cela donnerait alors :

sub add_object {
my ($handle, $id, $file, $note) = @_;
warn "$handle already defined in %h_object !"
if defined $h_objects{$handle};
$h_objects{$handle} = {
id => $id,
file => $file,
note => $note,
users => [],
};
}


sub show_array_type_id {
my $ref = shift;
warn "nb users : ", scalar(@$ref), "n";
foreach my $user (@$ref) {
warn "ttype $user->{type}, id $user->{id}n";
}
}

sub add_object_user {
my($handle,$type,$id)=@_;

warn "Ajout de l'utilisateur $id  type $type à l'objet
$h_objects{$handle}{file}n";

warn "Avantn";
show_array_type_id($h_objects{$handle}{users});

push @{$h_objects{$handle}{users}}, {type => $type, id => $id};

warn "Aprèsn";
show_array_type_id($h_objects{$handle}{users});
}



Pratiquant Perl de manière épisodique, je ne connaissais pas ce type de
construction.
Le programme semble fonctionner parfaitement.
Apparemment, je sais lire Perl mais ne le parle pas couramment. :-)

Merci.
Paul Gaborit
Le #20246431
À (at) Mon, 28 Sep 2009 18:08:58 +0200,
JB
Pratiquant Perl de manière épisodique, je ne connaissais pas ce type de
construction.



Ce sont que de simples tables de hachage anonymes qui sont aux tables
de hachage ce que sont les tableaux anonymes aux tableaux. Les objets
anonymes (tables de hachage, tableaux ou scalaires) se manipulent via
des références.

Tout cela est très bien expliqué dans perlreftut et perlref :


On trouve aussi quelques bons exemples dans perldsc :


Et pour une lecture hors-ligne (mais en anglais) :

% perldoc perlreftut
% perldoc perlref
% perldoc perldsc

Le programme semble fonctionner parfaitement.



Ouf... Je n'avais rien vérifié.

Apparemment, je sais lire Perl mais ne le parle pas couramment. :-)



C'est comme ça pour tout le monde et pour tous les langages : on écrit
toujours avec un sous-ensemble de ce qu'on sait lire (l'inverse serait
carrément surprenant). Mais c'est aussi en regardant comment les
autres écrivent qu'on peut améliorer son style et augmenter son
vocabulaire. ;-)

--
Paul Gaborit - Perl en français -
espie
Le #20246421
In article Paul Gaborit
C'est comme ça pour tout le monde et pour tous les langages : on écrit
toujours avec un sous-ensemble de ce qu'on sait lire (l'inverse serait
carrément surprenant). Mais c'est aussi en regardant comment les
autres écrivent qu'on peut améliorer son style et augmenter son
vocabulaire. ;-)



Ah tiens, moi j'ai deja ete surpris alors. Pour certains, la programmation
se rapproche de la magie noire. C'est aussi la technique shadock: on essaie
des trucs sans bien comprendre jusqu'a avoir le resultat attendu.

(bon je dis pas que ca donne des programmes lisibles et maintenables...)
Paul Gaborit
Le #20246531
À (at) Mon, 28 Sep 2009 18:40:13 +0000 (UTC),
(Marc Espie) écrivait (wrote):
Ah tiens, moi j'ai deja ete surpris alors. Pour certains, la programmation
se rapproche de la magie noire. C'est aussi la technique shadock: on essaie
des trucs sans bien comprendre jusqu'a avoir le resultat attendu.



C'est la technique du singe de Borges : il tape n'importe quoi (sans
jamais se répéter) et on attend qu'il sorte le livre qui
révolutionnera le monde.

(bon je dis pas que ca donne des programmes lisibles et maintenables...)



"Lisibles" et "maintenables" sont des caractéristiques mineures
comparées à "corrects" (dans le sens "qui donne le bon résultat"). Et
celle-là me semble peu probable : on attend toujours la fusée shadock
qui marche. ;-)

Par contre, la méthode par essais et erreurs est bonne si on peut la
combiner avec de la lecture de documentation qui permettent de
comprendre les résultats (bons ou mauvais).

--
Paul Gaborit - Perl en français -
JB
Le #20246651
Paul Gaborit wrote:


À (at) Mon, 28 Sep 2009 18:08:58 +0200,
JB
Pratiquant Perl de manière épisodique, je ne connaissais pas ce type de
construction.



Ce sont que de simples tables de hachage anonymes qui sont aux tables
de hachage ce que sont les tableaux anonymes aux tableaux. Les objets
anonymes (tables de hachage, tableaux ou scalaires) se manipulent via
des références.

Tout cela est très bien expliqué dans perlreftut et perlref :


On trouve aussi quelques bons exemples dans perldsc :


Et pour une lecture hors-ligne (mais en anglais) :

% perldoc perlreftut
% perldoc perlref
% perldoc perldsc

Le programme semble fonctionner parfaitement.






Je vais regarde cela.

Ouf... Je n'avais rien vérifié.

Apparemment, je sais lire Perl mais ne le parle pas couramment. :-)



C'est comme ça pour tout le monde et pour tous les langages : on écrit
toujours avec un sous-ensemble de ce qu'on sait lire (l'inverse serait
carrément surprenant). Mais c'est aussi en regardant comment les
autres écrivent qu'on peut améliorer son style et augmenter son
vocabulaire. ;-)



J'en suis persuadé mais je pense qu'il faut acquérir une culture perlienne.
À la différence de langage de type C ou Pascal, Perl a un gros moteur sous
le capot ce qui lui permet de faire magiquement des choses intéressantes,
encore faut-il connaître ces possibilités.
Je vais essayer de revoir le programme que j'avais démarré il y a un peu
plus d'un an et que je reprend parfois quand je veux un nouveau rapport.

Ceci m'amène à la question suivante : J'ai utilisée la solution avec des
hash, est-ce que celle-ci est plus gourmande en mémoire que la solution
avec des tableaux. Je pense que oui mais je peux me tromper.

Cordialement.
espie
Le #20246851
In article JB
J'en suis persuadé mais je pense qu'il faut acquérir une culture perlienne.
À la différence de langage de type C ou Pascal, Perl a un gros moteur sous
le capot ce qui lui permet de faire magiquement des choses intéressantes,
encore faut-il connaître ces possibilités.



C'est pas different des autres langages. Il y a une culture C. Et on peut
faire plein de choses en C avec tres peu de lignes de code, a partir du
moment ou on connait les bibliotheques existantes. C'est vrai pour la
plupart des vrais langages (pascal a un statut un peu particulier, etant
un langage d'enseignement sans culture tres profonde... faut aller gratter
dans les dialectes a la turbo-pascal ou delphi), et j'en suis meme a
conseiller certains langages pour leur culture plus que pour d'autres
qualites, perl en tete ! C'est pas le langage le plus propre, mais c'est
clairement un de ceux qui a la communaute la plus interessante...

fin de digression.


Je vais essayer de revoir le programme que j'avais démarré il y a un peu
plus d'un an et que je reprend parfois quand je veux un nouveau rapport.

Ceci m'amène à la question suivante : J'ai utilisée la solution avec des
hash, est-ce que celle-ci est plus gourmande en mémoire que la solution
avec des tableaux. Je pense que oui mais je peux me tromper.



Tu peux en avoir le coeur net: je t'enjoins a jouer avec Devel::Size.
JB
Le #20247061
Marc Espie wrote:


Ceci m'amène à la question suivante : J'ai utilisée la solution avec des
hash, est-ce que celle-ci est plus gourmande en mémoire que la solution
avec des tableaux. Je pense que oui mais je peux me tromper.



Tu peux en avoir le coeur net: je t'enjoins a jouer avec Devel::Size.


D'accord mais je voudrais savoir à priori si cela prend plus ou moins de
mémoire.
Paul Gaborit
Le #20248121
À (at) Mon, 28 Sep 2009 21:02:10 +0200,
JB
Ceci m'amène à la question suivante : J'ai utilisée la solution avec des
hash, est-ce que celle-ci est plus gourmande en mémoire que la solution
avec des tableaux. Je pense que oui mais je peux me tromper.



La réponse simple est oui. Mais pour une réponse plus éclairante, je
préfère vous citer un extrait de 'perltoot' :

Vous pourriez penser que l'accès au tableau est plus rapide que
l'accès à la table de hachage, mais ils sont en fait
comparables. Le tableau est un tout petit peu plus rapide, mais pas
plus de 10 ou 15%[...]. La plus grande différence entre les deux
approches est l'utilisation de la mémoire. La représentation par
table de hachage prend plus de mémoire que la représentation par
tableau parce qu'il faut allouer de la mémoire pour stocker les
clés d'accès en plus des valeurs. Par contre, ce n'est pas vraiment
mauvais puisque, depuis la version 5.004, le mémoire n'est allouée
qu'une seule fois pour une clé donnée indépendamment du nombre de
tables de hachage qui utilisent cette clé.[...]

(cf.
--
Paul Gaborit - Perl en français -
JB
Le #20248451
Paul Gaborit wrote:


À (at) Mon, 28 Sep 2009 21:02:10 +0200,
JB
Ceci m'amène à la question suivante : J'ai utilisée la solution avec des
hash, est-ce que celle-ci est plus gourmande en mémoire que la solution
avec des tableaux. Je pense que oui mais je peux me tromper.



La réponse simple est oui. Mais pour une réponse plus éclairante, je
préfère vous citer un extrait de 'perltoot' :

Vous pourriez penser que l'accès au tableau est plus rapide que
l'accès à la table de hachage, mais ils sont en fait
comparables. Le tableau est un tout petit peu plus rapide, mais pas
plus de 10 ou 15%[...]. La plus grande différence entre les deux
approches est l'utilisation de la mémoire. La représentation par
table de hachage prend plus de mémoire que la représentation par
tableau parce qu'il faut allouer de la mémoire pour stocker les
clés d'accès en plus des valeurs. Par contre, ce n'est pas vraiment
mauvais puisque, depuis la version 5.004, le mémoire n'est allouée
qu'une seule fois pour une clé donnée indépendamment du nombre de
tables de hachage qui utilisent cette clé.[...]

(cf.






Merci, je vais m'y mettre.
Publicité
Poster une réponse
Anonyme