Les Allergies
Alimentaires
Posez votre question Signaler

PERL : push dans un tableau ou hash [Résolu]

sbouli 171Messages postés 20 décembre 2007Date d'inscription 13 décembre 2011Dernière intervention - Dernière réponse le 22 oct. 2008 à 14:58
Bonjour,
Je ne comprend pas pourquoi le code ci-après me renvois des doubles dans le tableau malgrés la commande exists ...
#!/usr/bin/env perl
my $raison="";
my %tableau;

for(my $cpt=0; $cpt <= 5; $cpt++){
	$token = "token ".$cpt;
	if ($cpt == 2) { $token = "token 1"; }
	print "compteur : $cpt\n";
	print "mot : $token\n";
	print "hash avant : \n\t@tableau";
	push @tableau, $token unless exists $tableau{$token};
	print "\n";
	print "hash apres : \n\t@tableau";
	print "\n\n";
}

Résultat :

compteur : 0
mot : token 0
hash avant : 
	
hash apres : 
	token 0

compteur : 1
mot : token 1
hash avant : 
	token 0
hash apres : 
	token 0 token 1

compteur : 2
mot : token 1
hash avant : 
	token 0 token 1
hash apres : 
	token 0 token 1 token 1

compteur : 3
mot : token 3
hash avant : 
	token 0 token 1 token 1
hash apres : 
	token 0 token 1 token 1 token 3

compteur : 4
mot : token 4
hash avant : 
	token 0 token 1 token 1 token 3
hash apres : 
	token 0 token 1 token 1 token 3 token 4

compteur : 5
mot : token 5
hash avant : 
	token 0 token 1 token 1 token 3 token 4
hash apres : 
	token 0 token 1 token 1 token 3 token 4 token 5
Lire la suite 

PERL : push dans un tableau ou hash »

14 réponses
Réponse
+0
moins plus
Re,

Alors tu fait comme ça
lami20j@debian:~/trash$ cat sbouli.pl
#!/usr/bin/env perl
my $raison="";
my %tableau;

for(my $cpt=0; $cpt <= 5; $cpt++){
        $token = "token ".$cpt;
        if ($cpt == 2) { $token = "token 1"; }
        print "compteur : $cpt\n";
        print "mot : $token\n";
        print "hash avant : \n\t@tableau";
        push @tableau, $token unless grep { /$token/ } @tableau;
        print "\n";
        print "hash apres : \n\t@tableau";
        print "\n\n";
}
lami20j@debian:~/trash$ perl sbouli.pl
compteur : 0
mot : token 0
hash avant :

hash apres :
        token 0

compteur : 1
mot : token 1
hash avant :
        token 0
hash apres :
        token 0 token 1

compteur : 2
mot : token 1
hash avant :
        token 0 token 1
hash apres :
        token 0 token 1

compteur : 3
mot : token 3
hash avant :
        token 0 token 1
hash apres :
        token 0 token 1 token 3

compteur : 4
mot : token 4
hash avant :
        token 0 token 1 token 3
hash apres :
        token 0 token 1 token 3 token 4

compteur : 5
mot : token 5
hash avant :
        token 0 token 1 token 3 token 4
hash apres :
        token 0 token 1 token 3 token 4 token 5
je te rappelle que tu dois tester les éléments du tableau et pas celle d'un hash qui n'existe pas
pour te convaincre tu peux ajouter à la fin, après la boucle
print scalar keys %tableau, "\n"; et tu verras le résultat

La fonction grep permet de vérifier si le tableau contient déjà un token

sbouli- 21 oct. 2008 à 19:06
super mais donc ... j'ai rien compris à la fonction exists .. je pensais que ça vérifiais l'existance de l'entrée dans le tableau (avec des [ ou le hash avec { )

stéphane
lami20j- 21 oct. 2008 à 19:20
Pour un hash la fonction exists vérifié si la clé existe mais dans ton cas il n'y a pas de sens vu que tu dois vérifier plutôt les éléments du tableau.

En revanche comme je te l'ai dit, ton hash ne contient rien. Donc exists ne trouve aucune clé. Son comportement est normal ;-)
Mais si tu insistes et pour voir que exists fonctionne comme tu le penses il y a un moyen ;-) (En fait il y a toujours un moyen, mais tu me demandes trop de réfléchir ;-DDDD
#!/usr/bin/env perl
my $raison="";
my %tableau;

for(my $cpt=0; $cpt <= 5; $cpt++){
        $token = "token ".$cpt;
        if ($cpt == 2) { $token = "token 1"; }
        print "compteur : $cpt\n";
        print "mot : $token\n";
        print "hash avant : \n\t@tableau";
        push @tableau, $token unless exists $tableau{$token};
        $tableau{$token}=();
        print "\n";
        print "hash apres : \n\t@tableau";
        print "\n\n";
}
print scalar keys %tableau, "\n";

En fait j'ajoute d'abord le token et ensuite je remplis le hachage avec le token.
Donc maintenant exists trouvera une par une les clés et s'il la trouve il ne va pas la remettre dans le tableau vu qu'il existe déjà.
Tu vois à la fin qu'il y a 5 clé (ce sont les tokens)
Ajouter un commentaire
Réponse
-1
moins plus
Salut,

C'est à cause de if ($cpt == 2) { $token = "token 1"; }
Quand tu as "token 2" pour l'affichage il sera remplacer par "token 1".

@tableau n'est pas un hash.

En fait @ tableau contiens une liste
%tableau contiens aussi une liste, mais les éléments sont par paire.
Si tu affecte %tableau à @tableau tu ne fait que mettre une liste à plat, mais le hash est perdu.

lami20j@debian:~/trash$ cat sbouli.pl
#!/usr/bin/perl
use strict;use warnings;

my $raison="";
my %tableau;
my @tableau;

for(my $cpt=0; $cpt <= 5; $cpt++){
        my $token = "token ".$cpt;
#if ($cpt == 2) { $token = "token 1"; }
        print "compteur : $cpt\n";
        print "mot : $token\n";
        print "hash avant : \n\t@tableau";
        push @tableau,$token unless exists  $tableau{$token};
        print "\n";
        print "hash apres : \n\t@tableau";
        print "\n\n";
}
__END__
lami20j@debian:~/trash$ perl sbouli.pl
compteur : 0
mot : token 0
hash avant :

hash apres :
        token 0

compteur : 1
mot : token 1
hash avant :
        token 0
hash apres :
        token 0 token 1

compteur : 2
mot : token 2
hash avant :
        token 0 token 1
hash apres :
        token 0 token 1 token 2

compteur : 3
mot : token 3
hash avant :
        token 0 token 1 token 2
hash apres :
        token 0 token 1 token 2 token 3

compteur : 4
mot : token 4
hash avant :
        token 0 token 1 token 2 token 3
hash apres :
        token 0 token 1 token 2 token 3 token 4

compteur : 5
mot : token 5
hash avant :
        token 0 token 1 token 2 token 3 token 4
hash apres :
        token 0 token 1 token 2 token 3 token 4 token 5

P.S. Tu n'a rien à me dire?!
sbouli- 21 oct. 2008 à 17:59
Hello cher lami20j :)


En fait ceci fait suite à nos mails ... tu n'as pas dû lire le dernier ...

Sinon pour :
"C'est à cause de if ($cpt == 2) { $token = "token 1"; }
Quand tu as "token 2" pour l'affichage il sera remplacer par "token 1". "

C'est voulu, j'essais de contruire un hash (ou un tableau dans le cas présent c'est pas dérangeant) avec les valeures :

token 1
token 1
token 3
token 4
token 5

je devrais avoir pour résultat :
token 1
token 3
token 4
token 5

mais pas 2 fois token 1 ... ya un unless exists

J'ai pas testé le code du post ... je vois ça dans la soirée ...

A +

Stéphane
Ajouter un commentaire
Réponse
-1
moins plus
Re,

alors fait comme ça
lami20j@debian:~/trash$ cat sbouli.pl
#!/usr/bin/perl
use strict;use warnings;

my $raison="";
my %tableau;
my @tableau;

for(my $cpt=0; $cpt <= 5; $cpt++){
        my $token = "token ".$cpt;
        if ($cpt == 2) { $token = "token 1"; }
        print "compteur : $cpt\n";
        print "mot : $token\n";
        print "hash avant : \n\t@tableau";
        unless (exists  $tableau{$token}) {
          push @tableau,$token if $cpt!=2;
        }
        print "\n";
        print "hash apres : \n\t@tableau";
        print "\n\n";
}
__END__
lami20j@debian:~/trash$ perl sbouli.pl
compteur : 0
mot : token 0
hash avant :

hash apres :
        token 0

compteur : 1
mot : token 1
hash avant :
        token 0
hash apres :
        token 0 token 1

compteur : 2
mot : token 1
hash avant :
        token 0 token 1
hash apres :
        token 0 token 1

compteur : 3
mot : token 3
hash avant :
        token 0 token 1
hash apres :
        token 0 token 1 token 3

compteur : 4
mot : token 4
hash avant :
        token 0 token 1 token 3
hash apres :
        token 0 token 1 token 3 token 4

compteur : 5
mot : token 5
hash avant :
        token 0 token 1 token 3 token 4
hash apres :
        token 0 token 1 token 3 token 4 token 5
mais c'est inutile puisque le même résultat tu l'obtiens avec
#!/usr/bin/perl
use strict;use warnings;

my @tableau;

for(my $cpt=0; $cpt <= 5; $cpt++){
        my $token = "token ".$cpt;
        if ($cpt == 2) { $token = "token 1"; }
        print "compteur : $cpt\n";
        print "mot : $token\n";
        print "hash avant : \n\t@tableau";
        push @tableau,$token if $cpt!=2;
        print "\n";
        print "hash apres : \n\t@tableau";
        print "\n\n";
}
__END__


sbouli- 21 oct. 2008 à 18:38
hahahahaha

bon, ceci est un exemple conçu pour montrer mon problème de exists,

J'ai donc fait une boucle de 1 à 5 et pour le 2 (j'aurais pu choisir le 3), je remet le même token que pour le 1

donc le code :

unless (exists  $tableau{$token}) {
          push @tableau,$token if $cpt!=2;
        }


ne sert à rien, pour quoi le "token 1" est-il ajouté à l'itération numéro 2 alors que "token 1" est DEJA présent dans le tableau ??

Je veux que seuls les nouveaux token soit inséré dans le tableau

itération 1 : Je passe sur "token 1" le tableau est vide, je lui ajoute "token 1"
itération 2 : Je passe sur "token 1" (forcé par le if) le tableau contient deja "token 1" donc je ne lui ajoute pas
itération 3 : je passe sur "token 3" le tableau ne contient pas encore "token 3" je l'ajoute
etc ...
Ajouter un commentaire
Réponse
-1
moins plus
ok, je suis pas sûr de moi donc je poursuis, imaginons que je travail sur un hash désormais et pas sur un tableau. L'ensemble clef valeur sous la forme :

(
clef token 1 valeur 2,
clef token 3 valeur 1,
clef token 4 valeur 1,
clef token 5 valeur 1
)


j'imagine un truc dans ce gout là ...
#!/usr/bin/env perl
my $raison="";
my %monhash;

for(my $cpt=0; $cpt <= 5; $cpt++){
	$token = "token ".$cpt;
	if ($cpt == 2) { $token = "token 1"; }
	print "compteur : $cpt\n";
	print "mot : $token\n";
	print "hash avant : \n\t";
	print %monhash;
if (exists $monhash{$token})  {
    $monhash{$token}++;
} else {
    push %monhash, $token
}
	print "\n";
	print "hash apres : \n\t";
	print %monhash;
	print "\n\n";
}
sbouli- 21 oct. 2008 à 20:50
ben tout betement ça doit être :

if (exists $tableau{$token})  {
    $tableau{$token}++;
} else {
    $tableau{$token}=1;
}
Ajouter un commentaire
Réponse
-1
moins plus
Re,

On ne peux pas faire push sur un hash
En revanche tu peux avoir un hash de tableau qui veut dire que pour chaque clé la valeur est un tableau anonyme
Par exemple
push @{$hash{$token}},$token
sbouli- 21 oct. 2008 à 20:51
yes,

Je pense avoir compris mon erreur

pour moi un hash c'est %monhash

alors qu'en c'est : monhash

on intervient sur les éléments avec $monhash{$clef} un peu comme un tableau $montableau[$position]

merci en tout cas ... je poursuis demain

Stéphane
Ajouter un commentaire
Réponse
-1
moins plus
Re,

Pour avoir une image d'un hash de tableau
%hash = {
          cle1 => [ "val1", "val2"],
          cle2 => [ "a"   , "b"   ],
};

sbouli- 22 oct. 2008 à 12:48
Si j'ai bien compris, on ne peut pas mettre un tableau dans un hash mais une référence à ce tableau,
moi je voudrais un hash internautes avec comme clef une adresse email et comme value un tableau :

%internautes :
email ---> email, id, nb, date1, date2, date3

exemple:

email_1@toto.com
email_1@toto.com, 1, 1, 20081022 12:30:00, 20081020 10:10:00, 'null'
email_2@toto.com
email_2@toto.com, 10, 2, 20081022 12:31:00, 20081019 20:15:05, 'null'
etc ....

mais ce bout de code ne me donne que le pointeur du tableau pas le tableau ....donc je n'ai tout le temps qu'un seul tableau modifié à chaque tour ....


#!/usr/bin/env perl
use Data::Dumper;

my %internautes;
my @temp_internaute;
my $addr;

for(my $i=1; $i<10; $i++) {
	
	$addr="email_".$i."@toto.com";
	$addr="email_".$i."@toto.com";
	
	if ( exists $internautes{$addr} ) {
			@temp_internaute=$internautes{$addr};
			$temp_internaute[2]++;
			$internautes{$addr}=\@temp_internaute;
	} else {
			@temp_internaute=($addr,15,1,'20081022 12:35:00', '20081020 12:30:00', 'null');
			$internautes{$addr}=\@temp_internaute;
	}
}
print Dumper %internautes;
__END__

Ajouter un commentaire
Réponse
-1
moins plus
J'ai réussi en faisant :

if ( exists $internautes{$addr} ) {
            $internautes{$addr}[2]++;
} else {
            @$temp_internaute=($addr,$raisons{$raison},1,&datetime, "$revMsgDateStr $msgHr:$msgMin:00", 'null');
            $internautes{$clef}=$temp_internaute;
            undef $temp_internaute;}
Ajouter un commentaire
Ce document intitulé « PERL : push dans un tableau ou hash » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Dossier à la une
Passage au tout numérique : quel coût pour les particuliers ?