Rechercher : dans
Par :

PERL : push dans un tableau ou hash

Dernière réponse le 22 oct 2008 à 14:58:08 sbouli, le 21 oct 2008 à 16:41:29 
 Signaler ce message aux modérateurs

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

Meilleures réponses pour « PERL : push dans un tableau ou hash » dans :
Trier un tableau sans utiliser la fonction sort VoirTrier un tableau sans utiliser la fonction sort D'abord on initialise une variable $max avec la 1ère valeur de tableau. Ensuite on va faire une boucle tant que le tableau contient encore des éléments. C'est avec la fonction splice qui a le rôle...
Inverser les éléments d'un tableau -Récursivité- VoirVoici une procédure récursive qui permet d’inverser les éléments d’une partie d’un tableau compris entre la position p et n : Procedure Inverser (Var t : Tab; p, n : Integer); Var aux : Real; Begin If p < n Then ...
Décaler les éléments d'un tableau (Rotation) -Récursivité- VoirVoici une procédure récursive qui permet de décaler tous les éléments d’un tableau d’une position à droite à partir de la position p Procedure Decaler (Var t : Tab; p, n : integer); Begin If p
Perl - les opérateurs VoirQu'est-ce qu'un opérateur? Les opérateurs sont des symboles qui permettent de manipuler des variables, c'est-à-dire effectuer des opérations, les évaluer, ... On distingue plusieurs types d'opérateurs : les opérateurs de calcul les...
Les variables avec Perl VoirConcept de variable avec Perl Une variable est un objet repéré par son nom, pouvant contenir des données, qui pourront être modifiées lors de l'exécution du programme. Les variables en langage Perl peuvent être de trois...
Javascript - l'objet Array VoirLes particularités de l'objet Array L'objet Array est un objet du noyau Javascript permettant de créer et de manipuler des tableaux. Voici la syntaxe à utiliser pour créer une variable tableau : var x = new Array(element1[, element2, ...]); Si...

1

lami20j, le 21 oct 2008 à 17:48:36

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?!
106485010510997108

Répondre à lami20j

2

sbouli, le 21 oct 2008 à 17:59:33

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

Répondre à sbouli

3

lami20j, le 21 oct 2008 à 18:11:29

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__


106485010510997108

Répondre à lami20j

4

sbouli, le 21 oct 2008 à 18:38:39

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 ...

Répondre à sbouli

5

lami20j, le 21 oct 2008 à 18:51:46

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

106485010510997108

Répondre à lami20j

6

sbouli, le 21 oct 2008 à 19:06:37

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

Répondre à sbouli

7

lami20j, le 21 oct 2008 à 19:20:44

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)
106485010510997108

Répondre à lami20j

8

sbouli, le 21 oct 2008 à 20:44:41

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";
}

Répondre à sbouli

9

sbouli, le 21 oct 2008 à 20:50:05

Ben tout betement ça doit être :

if (exists $tableau{$token})  {
    $tableau{$token}++;
} else {
    $tableau{$token}=1;
}

Répondre à sbouli

10

lami20j, le 21 oct 2008 à 20:50:14

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
106485010510997108

Répondre à lami20j

11

sbouli, le 21 oct 2008 à 20:51:58

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

Répondre à sbouli

12

lami20j, le 21 oct 2008 à 20:55:57

Re,

Pour avoir une image d'un hash de tableau

%hash = {
          cle1 => [ "val1", "val2"],
          cle2 => [ "a"   , "b"   ],
};

106485010510997108

Répondre à lami20j

13

sbouli, le 22 oct 2008 à 12:48:32

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__

Répondre à sbouli

14

 sbouli, le 22 oct 2008 à 14:58:08

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;}

Répondre à sbouli