FAQ PerlConsultez toutes les FAQ

Nombre d'auteurs : 18, nombre de questions : 250, dernière mise à jour : 29 octobre 2015  Ajouter une question

 

Bienvenue sur la FAQ Perl. Cette FAQ a pour vocation de vous enseigner ou de vous faire revoir les notions élémentaires de ce fantastique langage. Perl est très utilisé dans différents domaines depuis la gestion système, le réseaux, l'administration de bases de données, le web (CGI), la bureautique, la conception d'interfaces graphiques ou des contextes scientifiques telle la bioinformatique. Nous espérons que cette FAQ vous sera d'une grande utilité.

Vous souhaitez participer à l'amélioration de cette FAQ, n'hésitez pas !! Commentez

Bonne lecture !


SommaireS'initier à PerlLes listes associatives (9)
précédent sommaire suivant
 

Une liste associative, ou table de hachage est un type de variable particulier contenant des scalaires associés entre eux par paires.
Chaque paire est constituée d'un premier élément, nommé "clef", qui servira de repère pour retrouver la valeur dans la table associative. Le second élément de la paire est la "valeur" qui sera stockée dans la table.
A chaque clef correspond une valeur. Il ne peut pas y avoir deux clefs identiques. Par contre, deux valeurs identiques peuvent être repérées par deux clefs distinctes.
La définition d'une paire ayant une clef déjà utilisée remplace la valeur associée à cette clef par la nouvelle valeur fournie.
Une liste associative peut s'exprimer par une ou plusieurs paires de valeurs, séparées par des virgules, mises entre parenthèses comme :

Code perl : Sélectionner tout
('a', 'chaîne a', 'b', 'chaîne b', 'zz', 'chaîne zz')
qui est l'expression d'une liste associative rassemblant les couples :

Code perl : Sélectionner tout
('a', 'chaîne a'), ('b', 'chaîne b'), ('zz', 'chaîne zz')
Le problème de cette notation est que l'on ne fait pas forcément la distinction entre listes et listes associatives. Cela peut être confortable pour passer d'une forme à l'autre, mais cela peut aussi être source d'erreur (notamment si l'on n'a pas mis un nombre pair de valeurs dans la table). C'est pourquoi il existe une autre notation qui met en évidence le caractère associatif des listes hachées :

Code perl : Sélectionner tout
('a' => 'chaîne a', 'b' => 'chaîne b', 'zz' => 'chaîne zz')
Ainsi, l'association clef/valeur est explicitement mise en évidence. Il est bien sûr nettement préférable d'utiliser cette notation. La nature des scalaires contenus dans une liste associative n'a absolument aucune espèce d'importance pour Perl. De même, la nature des valeurs utilisées comme clefs n'est pas critique. Les clefs doivent simplement correspondre à une chaîne de caractères, au sens large.

Perl est assez permissif sur la syntaxe des clefs et autorise, soit leur écriture entre quotes simples ou doubles, soit leur écriture sans quotes si la chaîne est composé exclusivement des lettres A à Z, a à z, des chiffres de 0 à 9 et du tiret de soulignement "_". De la même manière que les listes simples, les listes associatives s'aplatissent les unes dans les autres :

Code perl : Sélectionner tout
(a => 'chaîne a', b => 'chaîne b', (A => 'chaîne A', B => 'chaîne B', C => 'chaîne C'), a => '2eme chaîne a');
définit une liste associative de cinq paires, dont les clefs sont 'a', 'b', 'A', 'B' et 'C'. La sixième paire définie utilisant de nouveau la clef 'a', la valeur associée 'chaîne a' sera remplacée par '2eme chaîne a'. La liste associative incluse a été aplatie et ses paires se retrouvent au même niveau que les paires de la liste principale.
Pour inclure une liste associative dans une autre, en lui conservant son caractère "liste", il sera nécessaire de faire appel à une notion avancée (que l'on verra ultérieurement) : les références.
Comme pour les listes simples, une liste associative vide est définie par une paire de parenthèses vides : () définit une liste (simple ou associative) ne contenant aucun élément.

Mis à jour le 5 mai 2005 2Eurocents

Les listes associatives que l'on vient de voir sont elles aussi un peu volatiles... nous ne les avons toujours pas rangées dans des variables.
Elles ne peuvent pas être conservées dans une variable scalaire ordinaire et les ranger dans une table ordinaire n'aurait pas de sens car on perdrait le caractère associatif. Perl utilise un type de variable spécial pour gérer les listes associatives.

Mis à jour le 5 mai 2005 2Eurocents

Une table associative est une variable dont le sigil (le caractère qui précède le nom) est % :

Code perl : Sélectionner tout
my %association = (1 => 'aaa', 2 => 'bbb', 3 => 'ccc');
L'usage de cette table se fait de deux manières, selon que l'on veut la manipuler dans sa globalité, ou bien accéder à un élément particulier. L'accès global au tableau associatif se fait avec la notation en %.

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
%hash = (); #pour vider un tableau de hachage. 
%hash = (1 => 'premier', 2 => 'deuxieme', 3 => 'troisieme'); # pour affecter une nouvelle liste associative. 
%hash = %list; # pour affecter le contenu d'un tableau associatif à un autre tableau de hachage (attention, il s'agit d'une duplication du contenu). 
  
# pour affecter le contenu de trois tableaux associatifs dans un autre. Les clefs présentes dans plusieurs tableaux  
# simultanément ne se retrouveront qu'en un exemplaire dans le hachage résultant avec pour valeur associée la dernière valeur rencontrée. 
%hash = (%hash1, %hash2, %hash3);  
  
# pour affecter une liste simple à une liste associative. Les éléments de la liste simple sont pris  
# par paires, le premier de chaque paire étant utilisé comme clef, le second comme valeur. 
%hash = @list;
Par contre, l'évaluation d'une table associative en contexte scalaire n'est, à priori, pas une idée pertinente.

Mis à jour le 5 mai 2005 2Eurocents

Puisque l'on ne peut pas évaluer la liste associative en contexte scalaire, contrairement aux listes simples, comment peut-on récupérer le nombre d'éléments d'une liste associative ?

Perl fournit deux fonctions particulières d'accès aux listes associatives : keys() et values().

  • keys() retourne une liste simple contenant toutes les clefs de la liste associative passée en paramètres ;
  • values() retourne une liste simple contenant toutes les valeurs de la liste associative passée en paramètres.

Pour connaître le nombre d'éléments de la liste associative, il faut trouver le nombre d'éléments d'une de ces deux listes simples. Par contre, il est important de savoir que l'ordre des éléments dans les listes retournées par keys() et values() n'a rien à voir avec l'ordre dans lequel les éléments ont été ajoutés au hachage.
Il s'agit d'un ordre qui permet à Perl d'optimiser ses recherches lorsque l'on souhaite accéder à un élément en particulier.

Mis à jour le 5 mai 2005 2Eurocents

Un tableau associatif contient des scalaires. Pour en récupérer un en particulier, il faut indiquer que l'on veut un scalaire, donc utiliser le sigil(1) $ devant le nom du tableau de hachage, et indiquer entre accolades la clef de celui que l'on souhaite récupérer.

$hash{aaa} correspond donc au scalaire se trouvant associé à la clef "aaa".

Notez bien que si la clef est bien une chaîne de caractères, il n'est pas nécessaire de la mettre entre quotes tant qu'elle ne contient pas d'espace ni de caractère susceptible de gêner l'interpréteur.
Si la clef fournie n'existe pas, Perl créera la paire d'éléments avec la clef d'une part, et la valeur "undef" d'autre part. Il est donc prudent, plutôt que de tenter d'accéder directement à des éléments dont on ne sait pas s'ils existent ou non, de les tester au préalable grâce à la fonction exists(). Ce qui ne vous empêche pas par ailleurs, de faire des tests sur la définition valide de son contenu par la fonction defined().

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
my %identite = ( 
  nom    => 'dupond', 
  prenom => 'jean', 
); 
  
if ( exists $identite{nom} ) { 
  print "Nom : $identite{nom}\n"; 
} 
  
if ( exists $identite{age} ) { 
  print "Age : $identite{age}\n"; 
}
Code : Sélectionner tout
Nom : dupond
  • Un sigil est le premier caractère d'un identificateur en Perl. Il est non alphanumérique et dénote son type.

Mis à jour le 5 mai 2005 2Eurocents

Pour lister le contenu d'un hash, il existe trois opérateurs nous facilitant la vie : keys, values et each.

  • keys retourne une liste simple contenant toutes les clefs de la liste associative ;
  • values retourne une liste simple contenant toutes les valeurs de la liste associative ;
  • each permet d'effectuer une itération sur l'ensemble des éléments d'un hash sans avoir à procéder à un accès préalable aux clefs.

Voici des exemples simples.

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/perl 
use warnings; 
use strict; 
  
my %hash = ( 
  'Nom'        => 'Dupond', 
  'Prenom'     => 'Jean', 
  'Adresse'    => '10 rue de Rome', 
  'Ville'      => 'Paris', 
  'CodePostal' => '75000' 
); 
  
print "Utilisation des clefs\n"; 
foreach my $clef ( keys %hash ) { 
  print "$clef : $hash{$clef}\n"; 
} 
  
print "\nUtilisation de each\n"; 
while ( my ( $clef, $valeur ) = each %hash ) { 
  print "$clef : $valeur\n"; 
} 
  
print "\nAffichage uniquement des valeurs\n"; 
foreach my $valeur ( values %hash ) { 
  print "$valeur\n"; 
}
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Utilisation des clefs 
Ville : Paris 
Adresse : 10 rue de Rome 
CodePostal : 75000 
Prenom : Jean 
Nom : Dupond 
 
Utilisation de each 
Ville : Paris 
Adresse : 10 rue de Rome 
CodePostal : 75000 
Prenom : Jean 
Nom : Dupond 
 
Affichage uniquement des valeurs 
Paris 
10 rue de Rome 
75000 
Jean 
Dupond
Il est impossible de trouver une clef à partir d'une valeur.

Mis à jour le 29 juin 2011 djibril

Il est possible de supprimer définitivement un élément de notre liste associative avec la fonction delete.
Depuis Perl 5.12, nous avons la possibilité de supprimer un élément de notre liste associative localement dans notre programme. Pour ce faire, il faut associer à delete la fonction local : delete locale $hash{clef}; Voici un exemple :

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/perl 
use warnings; 
use strict; 
  
my %hash = ( 
  'Nom'        => 'Dupond', 
  'Prenom'     => 'Jean', 
  'Adresse'    => '10 rue de Rome', 
  'Ville'      => 'Paris', 
  'CodePostal' => '75000' 
); 
  
print "\nListons le contenu du hash\n"; 
while ( my ( $clef, $valeur ) = each %hash ) { 
  print "$clef : $valeur\n"; 
} 
  
# supprimons localement 2 éléments 
{ 
  delete local $hash{Nom}; 
  delete local $hash{CodePostal}; 
  
  print "\nListons localement le contenu du hash\n"; 
  while ( my ( $clef, $valeur ) = each %hash ) { 
    print "$clef : $valeur\n"; 
  } 
  
} 
  
print "\nListons le contenu du hash - version 2\n"; 
while ( my ( $clef, $valeur ) = each %hash ) { 
  print "$clef : $valeur\n"; 
}
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Listons le contenu du hash 
Ville : Paris 
Adresse : 10 rue de Rome 
CodePostal : 75000 
Prenom : Jean 
Nom : Dupond 
 
Listons localement le contenu du hash 
Ville : Paris 
Adresse : 10 rue de Rome 
Prenom : Jean 
 
Listons le contenu du hash - version 2 
Ville : Paris 
Adresse : 10 rue de Rome 
CodePostal : 75000 
Prenom : Jean 
Nom : Dupond

Mis à jour le 29 juin 2011 djibril

Une tranche est une façon commune d'accéder à une liste ou liste associative afin d'en prendre plusieurs éléments simultanément. Les tranches permettent de compacter notre code en évitant des appels individuels aux éléments.

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/perl 
use strict; 
use warnings; 
  
my @liste = ( 1 .. 10 ); 
my @tranche_liste = @liste[ 2, 4, 0 ]; 
print "Tranche de liste : @tranche_liste\n"; 
  
my %liste_associative = ( 
  nom     => 'dupond', 
  prenom  => 'jean', 
  age     => '22', 
  sexe    => 'masculin', 
  langage => 'perl', 
); 
my @tranche_liste_associative = @liste_associative{ 'prenom', 'age', 'langage' }; 
print "Tranche de liste associative : @tranche_liste_associative\n";
Code : Sélectionner tout
1
2
Tranche de liste : 3 5 1 
Tranche de liste associative : jean 22 perl
Si vous êtes troublé par l'usage d'un "@" ici sur une tranche de hachage au lieu d'un "%", pensez-y ainsi. Le type de parenthésage (avec des crochets ou des accolades) décide si c'est un tableau ou un hachage qui est examiné. D'un autre côté, le symbole en préfixe ("$" ou "@") du tableau ou du hachage indique si vous récupérez une valeur simple (un scalaire) ou une valeur multiple (une liste).

Mis à jour le 5 mai 2005 djibril

Les fonctions shift(), unshift(), pop() et push() n'ont pas de raison d'être utilisées avec les tables associatives, l'ordre des éléments étant inconnu et déterminé automatiquement par Perl. Les fonctions split() et join() aussi n'ont plus de sens... mais que reste-t-il alors ?

delete() supprime toujours l'élément fourni.

Code perl : Sélectionner tout
delete $h{clef}
Il supprime l'élément de la table de hachage %h, dont la clef est 'clef'. Sa valeur n'est pas seulement mise à undef. Sa clef est également supprimée et les tests avec exists $h{clef} seront faux.

reverse() permet d'inverser une liste. Dans le cas d'une table de hachage, il fait un échange entre les clefs et les valeurs. Les clefs deviennent les valeurs et les valeurs deviennent les clefs. Cela fonctionne très bien si les valeurs sont uniques. Dans le cas contraire, on ne peut pas prévoir quels seront les couples clef/valeur qui seront conservés pour les valeurs de départ en double.

sort() ne peut pas trier une liste associative, mais permet, grâce à son bloc d'instructions, toutes sortes de tris sur les clefs ou sur les valeurs. Ainsi, pour un tri lexicographique des clefs de %t, on peut faire :

Code perl : Sélectionner tout
@l = sort { $a cmp $b } keys %t;
qui fournit une liste des clefs triées. Pour un tri lexicographique des valeurs de %t, on peut faire :

Code perl : Sélectionner tout
@l = sort { $a cmp $b } values %t;
qui fournit une liste des valeurs triées - mais l'on a perdu les clefs associées. Pour un tri lexicographique des clefs de %t, selon leurs valeurs associées, on peut faire :

Code perl : Sélectionner tout
@l = sort { $t{$a} cmp $t{$b} } keys %t;
qui fournit une liste des clefs triées selon les valeurs associées croissantes - on a bien trié une liste simple de clef, mais le bloc d'instructions faisait la comparaison sur les valeurs liées. map() et grep() ne parcourront pas directement une table associative mais permettent tout traitement sur les listes de clefs ou les listes de valeurs. Pour reprendre l'exemple scolaire qui clôturait le chapitre sur les listes, en voici une réécriture plus pertinente au moyen de listes associatives :

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Préparation des données 
my %moyennes = ( 
	'Valentine' => 8, 
	'Chloé' => 16, 
	'Sophie' => 19, 
	'Olivier' => 12, 
	'Jérôme' => 6, 
	'Samuel' => 15 
); 
  
# Fin de la préparation... 
# Relevé des notes permettant le passage en classe supérieure 
# et liste des élèves admis, traitement simultané 
my @passent = grep { $moyenne{$_} >= 10 } keys %moyennes;
Cette réécriture du traitement est plus efficace, plus facile à maintenir et plus sûre que celle basée sur les tableaux. En outre, nous commençons à peine à ébaucher la puissance de Perl. Nous avons réalisé ce type de traitement de sélection, simplement en manipulant des données, sans construction de traitements complexes. Nous allons maintenant pouvoir ajouter tout ce qui est nécessaire au contrôle fin de l'exécution des traitements...

Mis à jour le 5 mai 2005 2Eurocents

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2017 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

 
Responsable bénévole de la rubrique Perl : djibril -