OVH Cloud OVH Cloud

Modification spontanée (?) d'un tableau

4 réponses
Avatar
Pascal
Hello,

Je bute sur un phenomène que je ne comprends pas.
Je désire compter le nombre de lignes d'un tableau de tableau qui ont la
meme valeur dans la case [$a][$colonne], $a variant de 1 à 21.

Une fois que j'ai le nombre (e.g., 1) de lignes qui ont toutes la meme
valeur (e.g., 2.7.4.9), je récupère un autre nombre associé à la valeur
2.7.4.9 (e.g., 10). Puis je fais le % (1/10*100). Bref, je mets toutes
ces infos dans la case [$a][$colonne].

Donc je pars de (pour $a = 1) $AvgSorted_new[$a][$colonne] = 2.7.4.9
et je veux arriver à tableau identique à @AvgSorted_new à cette case
près : $AvgSorted_new_forTE[$a][$colonne] = 2.7.4.9,1,10,10

Bref, j'ai le code et le résultat suivant :

ssfct($#AvgSorted_new+1,@AvgSorted_new,@AvgSorted_new);

sub ssfct {
$nb = splice(@_,0,1);
@AvgSorted_new = splice(@_,0,$nb);
@AvgSorted_new_forTE = splice(@_,0);

print "FIRST et pour a $a avant while if|
$AvgSorted_new[$a][$colonne]\n";
# ca m'imprime logiquement :
# FIRST et pour a 1 avant while if| 2.7.4.9

while(defined($ligne = <LIST_FILE>)) { # la ligne est p.ex. "2.7.4.9 :
10"
my @valeurs = split(' : ', $ligne);
chomp $valeurs[1];
if ($valeurs[0] eq $AvgSorted_new[$a][$colonne]) {
my $taux_enr = $compteur/$valeurs[1]*100;
$taux_enr = sprintf("%.f",$taux_enr);
my $temp = "$AvgSorted_new_forTE[$a][$colonne]";
$AvgSorted_new_forTE[$a][$colonne] =
"$temp,$compteur,$valeurs[1],$taux_enr";
print "et pour a $a dans while if| $AvgSorted_new[$a][$colonne]\n";
# ca m'imprime, bien qu'il me semble ne pas avoir touché à
@AvgSorted_new :
# et pour a 1 dans while if| 2.7.4.9,1,10,10
last;
}
}
}


Quelqu'un voit-il ou est mon erreur ?

Au plaisir de lire vos conseils...
Cordialement,
Pascal

4 réponses

Avatar
Paul GABORIT
À (at) Tue, 25 May 2004 17:51:08 +0200,
Pascal écrivait (wrote):
Je bute sur un phenomène que je ne comprends pas.
[... du code incompréhensible ...]

Quelqu'un voit-il ou est mon erreur ?


Essayez le code suivant :

my @a = ([1], [3]);
my @b = @a;
$b[1] = [@{$a[1]}];
$b[0][0] = 10;
$b[1][0] = 10;

print "$a[0][0], $b[0][0]n";
print "$a[1][0], $b[1][0]n";

Ça affiche :

10, 10
3, 10

En fait, après la copie de @a dans @b, les tableaux @a et @b ne contiennent
pas les même valeurs mais leurs éléments font références aux *mêmes*
sous-tableaux.


$b[1] = [@{$a[1]}];

on crée une référence vers une *copie* du second sous-tableau de @a.

Pour faire une véritable copie en *profondeur* de quasiment n'importe quelle
structure de données Perl, vous pouvez utiliser la fonction 'dclone' fournie
par le module Storable (cf. perldoc Storable).

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>

Avatar
Pascal
H'lo,

[... du code incompréhensible ...]


Oh, à ce point-là ? ;)
Va falloir que je tente d'éclaircir le code, alors. Sauf que je ne sais
pas encore comment ;)

En fait, après la copie de @a dans @b, les tableaux @a et @b ne contiennent
pas les même valeurs mais leurs éléments font références aux *mêmes*
sous-tableaux.


Ah ? Donc, si je modifie une case de @b, la case correspondante de @a
est aussi modifiée ?


$b[1] = [@{$a[1]}];

on crée une référence vers une *copie* du second sous-tableau de @a.


Mais là, je peux donc modifier $b[1] sans affecter @a, ai-je bien
compris ?

Pour faire une véritable copie en *profondeur* de quasiment n'importe quelle
structure de données Perl, vous pouvez utiliser la fonction 'dclone' fournie
par le module Storable (cf. perldoc Storable).


Ouich, je vais voir si j'arrive à utiliser l'un ou l'autre...

Merci ;)

Cordialement,
Pascal

Avatar
Paul GABORIT
À (at) Thu, 27 May 2004 09:18:23 +0200,
Pascal écrivait (wrote):
En fait, après la copie de @a dans @b, les tableaux @a et @b ne contiennent
pas les même valeurs mais leurs éléments font références aux *mêmes*
sous-tableaux.


Ah ? Donc, si je modifie une case de @b, la case correspondante de @a
est aussi modifiée ?


Non : les éléments de @a et @b sont différents. En revanche, si vous utilisez
la référence stockée dans une case de @b pour accéder à l'un des
sous-tableaux, vous modifiez le même sous-tableau que celui auquel fait
référence l'élément correspondant de @a. Quelques petits dessins valent
parfois mieux qu'un long discours.


@a = ([1,2],[3,4]);

@a
+------+
| | +-----+-----+
| ref--+--------->| 1 | 2 |
| | +-----+-----+
+------+
| | +-----+-----+
| ref--+--------->| 3 | 4 |
| | +-----+-----+
+------+

@b = @a;

@a @b
+------+ +------+
| | +-----+-----+ | |
| ref--+--------->| 1 | 2 |<-----------+--ref |
| | +-----+-----+ | |
+------+ +------+
| | +-----+-----+ | |
| ref--+--------->| 3 | 4 |<-----------+--ref |
| | +-----+-----+ | |
+------+ +------+

$b[0][0] = 9;

@a @b
+------+ +------+
| | +-----+-----+ | |
| ref--+--------->| 9 | 2 |<-----------+--ref |
| | +-----+-----+ | |
+------+ +------+
| | +-----+-----+ | |
| ref--+--------->| 3 | 4 |<-----------+--ref |
| | +-----+-----+ | |
+------+ +------+

$b[0] = [5, 6];

@a @b
+------+ +------+
| | +-----+-----+ | | +-----+-----+
| ref--+--------->| 9 | 2 | + ref--+--->| 5 | 6 |
| | +-----+-----+ | | +-----+-----+
+------+ +------+
| | +-----+-----+ | |
| ref--+--------->| 3 | 4 |<-----------+--ref |
| | +-----+-----+ | |
+------+ +------+

$b[1] = $a[0];

@a @b
+------+ +------+
| | +-----+-----+ | | +-----+-----+
| ref--+--------->| 9 | 2 |<----+ + ref--+--->| 5 | 6 |
| | +-----+-----+ | | | +-----+-----+
+------+ | +------+
| | +-----+-----+ | | |
| ref--+--------->| 3 | 4 | +------+--ref |
| | +-----+-----+ | |
+------+ +------+

$b[1] = [@{$a[0]}];

@a @b
+------+ +------+
| | +-----+-----+ | | +-----+-----+
| ref--+--------->| 9 | 2 | + ref--+--->| 5 | 6 |
| | +-----+-----+ | | +-----+-----+
+------+ +------+
| | +-----+-----+ | | +-----+-----+
| ref--+--------->| 3 | 4 | | ref--+--->| 9 | 2 |
| | +-----+-----+ | | +-----+-----+
+------+ +------+

Etc.

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>


Avatar
Pascal
H'lo,

Quelques petits dessins valent parfois mieux qu'un long discours.
(...)


Ouich wonderful, je crois avoir compris ;)
Il me reste juste à arriver à mettre ces subtilités en pratique !

Merci beaucoup !
Cordialement,
Pascal