Programmation Perl/Fonctions sur listes
Rappels sur les listes.
Une liste est une suite de mots, de nombres… tout scalaire à vrai dire.
Une liste stockée forme un tableau ou un tableau associatif (que nous verrons plus loin).
une liste.
Pour créer une liste on utilise les parenthèses "()" de cette manière :
Nous avons là une suite de scalaires : "5.0", "truc", 7 et la valeur stockée dans la variable scalaire $autre_valeur.
créer un tableau.
Pour pouvoir la manipuler plus tard dans le programme, nous la stockons dans une variable.
La variable est donc un tableau signalé par le sigil @.
Exemple avec parenthèses :
my @bon_a_manger = ( "poire", "chocolat", "sucre", "sirop", "bonbons", "fromage" );
Mais il y a d'autres opérateurs dédiés à la création de listes, comme "qw" qui crée une liste de mots ("quoted words").
Cet opérateur est préféré aux parenthèses dû à sa concision.
Exemple avec qw : 
my @bon_a_manger = qw/poire chocolat sucre sirop bonbons fromage/;
La création de la liste est plus concise. 
Mais ceci va plus loin encore (voir la création de tableaux associatifs avec qw).
Créer un tableau associatif.
Un tableau associatif (ou "table de hachage") est une structure permettant d'associer à un scalaire un autre scalaire.
C'est une liste un peu plus complexe qu'un tableau et le sigil est différent ("%").
La création de ce type de liste se fait également avec des parenthèses, mais on ajoute également (facultatif) un opérateur "=>" pour voir facilement la clé et sa valeur :
my %bon_a_manger = ( "fruit" => "cerise", "légume" => "patate" );
À savoir : l'opérateur "=>" force l'interprétation de la variable à sa gauche comme une chaîne de caractères, donc les guillemets sont inutiles.
Même exemple, mais avec qw : 
my %bon_a_manger = qw/fruit cerise légume patate/;
Là encore nous voyons la concision apportée par cet opérateur.
%bon_a_manger a le sigil "%" donc Perl sait qu'il doit ranger les mots par paires de la manière clé-valeur ("fruit" => "cerise", "légume" => "patate").
Fonctions de manipulation de listes.
Il existe un nombre assez conséquent de fonctions de manipulation de listes (tableaux, tableaux associatifs).
Nous allons aborder les plus courantes.
Il n'est pas obligatoire de les connaître toutes par cœur.
.. : créer une suite d'éléments.
On pourrait vouloir par exemple créer des suites longues d'éléments qui s'enchaînent.
Par exemple, avec l'opérateur .. écrire une suite de 1 à 100 n'est pas plus compliqué que :
( 1 .. 100 ) # toutes les valeurs entières de 1 à 100
Nous pouvons faire également la même chose avec des lettres :
( 'a' .. 'z' ) # renvoie toutes les lettres de l'alphabet
exemple : les lettres de 'a' à 'zz'.
Nous allons afficher à l'écran toutes les combinaisons des lettres de 'a' à 'zz' :
foreach my $var ( 'a' .. 'zz' )
 say $var; # affiche tour à tour chacune des valeurs de 'a' à 'zz'
join : concatène tous les éléments d'une liste.
La commande "join" permet de concaténer tous les éléments d'une liste avec un motif (une chaîne de caractères par exemple) entre chaque élément.
Exemple : afficher tous les éléments d'un tableau séparés par un double point.
my @fruits = qw/ poire cerise pomme fraise /;
say join(' : ', @fruits);
Affichera : « poire : cerise : pomme : fraise ».
map : transforme tous les éléments d'une liste.
Conseil : pour comprendre correctement cette fonction, voyez au moins le cours sur les fonctions et les procédures.
Cette fonction applique une transformation à tous les éléments d'un tableau ou d'une table de hachage.
"map" prend en argument un bloc de code à exécuter et une liste (ou tableau).
Il retourne une liste d'éléments modifiés.
Un exemple simple, on va doubler les valeurs d'un tableau :
my @simple = ( 1 .. 3 );
my @double = map { $_ * 2 } @simple; # on double toutes les valeurs
say foreach @double; # 246
Comme plus haut mais en une seule ligne :
say foreach map { $_ * 2 } ( 1 .. 3 ) ; # ce code est un peu plus dur à lire que les autres, n'hésitez pas à le relire plusieurs fois
Écrire du code aussi compact est très pratique à l'usage, mais pour un débutant il n'est pas nécessaire de savoir écrire de façon aussi concise.
grep : récupère une partie des éléments d'une liste.
Se manipule comme "map", et permet de récupérer une liste d'éléments contenus dans une liste suivant certaines conditions. 
Exemple : les éléments numériques inférieurs à 10 :
my @tableau_1_a_100 = ( 1 .. 100 );
my @inferieurs_a_10 = grep { $_ < 10 } @tableau_1_a_100 ;
say foreach @inferieurs_a_10; # affiche chaque élément de @inferieurs_a_10 suivit d'un retour à la ligne
exists : savoir si un élément d'une liste existe.
Cette fonction permet de savoir si un élément d'une liste existe.
Attention : ceci ne permet pas de savoir si l'élément est "défini".
keys : retourne toutes les clés d'une table de hachage.
Renvoie une liste des clés d'une table de hachage.
my %hash = qw/ fruit poire légume carotte/;
say join(' : ', keys (%hash));
Affiche : « légume : fruit ».
values : retourne toutes les valeurs d'une table de hachage.
Renvoie une liste des valeurs contenues dans une table de hachage.
my %hash = qw/ fruit poire légume carotte/;
say join(' : ', values(%hash));
each : retourne un couple clé-valeur d'une table de hachage.
Cette fonction est très utile pour boucler sur tous les éléments d'un tableau associatif.
my %hash = qw/ fruit poire légume carotte/;
say "Un couple 'clé - valeur' : ", join( " - " , each %hash);
Affichera : « Un couple 'clé - valeur' : légume - carotte » .
pop : retire le dernier élément d'une liste et le retourne.
Permet de supprimer le dernier élément d'une liste.
Il retourne cet élément, donc on peut le récupérer.
my @fruits = qw/ poire cerise pomme fraise /;
say pop @fruits; # affichera "fraise"
push : ajoute à la fin de la liste un nouvel élément.
Cette fonction ajoute un élément à la fin d'une liste.
On reprend l'exemple plus haut en ajoutant "push" pour remettre « fraise » :
my @fruits = qw/ poire cerise pomme fraise /;
say pop @fruits; # affichera "fraise"
push @fruits, "fraise"; # @fruits contient à nouveau "fraise" en dernière position
shift : supprime le premier élément d'une liste et le retourne.
Il suffit de faire shift @tableau, exemple :
my @bon_a_manger = qw/fruit cerise légume patate /; # un simple tableau
my $aliment = shift @bon_a_manger; # on supprime le premier élément du tableau et on le récupère (facultatif)
say $aliment; # affichera « fruit » qui était le premier élément de @bon_a_manger
say join ':', @bon_a_manger; # affichera « cerise:légume:patate »
unshift : ajoute un élément au début d'une liste.
Exemple simple d'utilisation de unshift :
my @bon_a_manger = qw/fruit cerise légume patate /; # un simple tableau
my $aliment = "fromage"; # un simple scalaire
unshift @bon_a_manger, $aliment; # on ajoute le scalaire "fromage" au début du tableau @bon_a_manger
say join ':', @bon_a_manger; # affichera « fromage:fruit:cerise:légume:patate »
reverse : inverse tous les éléments d'une liste (le dernier devient premier, etc.).
On fait simplement reverse @tableau.
Le tri alphabétique inverse en devient on ne peut plus clair.
use strict;
my @tableau = qw(d a c e b);
my @tri = reverse sort @tableau; # e d c b a
print "@tri\n";#
splice : manipule des "tranches" de listes.
use strict;
use warnings;
my @tableau= qw(ba be bi bo bu fa fe fi fo fu);
print splice (@tableau,2,3)."\n"; # bu dernier éliminé après bi et bo
print "@tableau\n";# ba be fa fe fi fo fu
@tableau= qw(ba be bi bo bu fa fe fi fo fu);
splice(@tableau,4,-2);
print "@tableau\n";# ba be bi bo fo fu
@tableau= qw(ba be bi bo bu fa fe fi fo fu);
splice(@tableau,-5,2);
print "@tableau\n";# ba be bi bo bu fi fo fu
@tableau= qw(ba be bi bo bu fa fe fi fo fu);
splice(@tableau,-4,-1);
print "@tableau\n";# ba be bi bo bu fa fu
@tableau= qw(ba be bi bo bu fa fe fi fo fu);
splice(@tableau,2,4,"XX");
print "@tableau\n";# ba be XX fe fi fo fu
@tableau= qw(ba be bi bo bu fa fe fi fo fu);
splice(@tableau,3,5);
print "@tableau\n";# ba be bi fo fu
@tableau= qw(ba be bi bo bu fa fe fi fo fu);
splice(@tableau,4,0,"YY");
print "@tableau\n";# ba be bi bo YY bu fa fe fi fo fu
@tableau= qw(ba be bi bo bu fa fe fi fo fu);
splice(@tableau,0,0,"PREF_");
print "@tableau\n";# PREF_ ba be bi bo bu fa fe fi fo fu
@tableau= qw(ba be bi bo bu fa fe fi fo fu);
my $Nombre = @tableau;
splice(@tableau,$Nombre,0,"_SUFF");# ba be bi bo bu fa fe fi fo fu _SUFF
print "@tableau\n";
scalar : retourne le nombre d'éléments d'une liste.
Cette fonction n'a aucune utilité si on est en contexte scalaire, par exemple : 
$nb_elements = @tableau;
Cependant, lorsque nous sommes en contexte de liste, il sera déjà plus utile :
my @tableau_1 = qw/voiture avion vélo/; # un tableau quelconque
my @tableau_2 = qw/train skateboard moto/; # un second tableau quelconque
my @nombres_elements = (scalar(@tableau_1), scalar(@tableau_2));
Ici, le code que nous avons créé permet de créer un tableau @nombres_elements qui contient le nombre d'éléments de deux précédents tableaux.
Sans scalar, nous aurions un tableau contenant l'ensemble des scalaires des deux premiers tableaux.
Cela est dû à "l'aplatissement" des tableaux.
sort : ordonne une liste.
use strict;
use warnings;
my @tableau = qw(9 -.2 -4 34 -7 0 111);
my @tri = sort @tableau;
print "@tri\n";# -.2 -4 -7 0 111 34 9
@tri = sort ({$a cmp $b} @tableau);
print "@tri\n";# -.2 -4 -7 0 111 34 9
@tri = sort ({$b cmp $a} @tableau); # autre syntaxe : @tri = reverse sort @tableau;
print "@tri\n";# 9 34 111 0 -7 -4 -.2
@tri = sort ({$a <=> $b} @tableau);
print "@tri\n";# -7 -4 -.2 0 9 34 111
@tri = sort ({$b <=> $a} @tableau);
print "@tri\n";# 111 34 9 0 -.2 -4 -7
@tableau = qw(3 1 6 5 3 1 6 5);
my $moitie = scalar @tableau / 2; # scalar est facultatif : my $... = environnement scalaire
@tri = ((sort ({$a <=> $b} splice (@tableau,0,$moitie))),(sort ({$b <=> $a} splice (@tableau,-$moitie,$moitie))));
print "@tri\n";# 1 3 5 6 6 5 3 1
@tableau = qw(9 -.2 -4 -14 -7 0 11);
@tri = sort ({abs $a <=> abs $b} @tableau);
print "@tri\n";# 0 -.2 -4 -7 9 11 -14
@tableau = qw(ab a abcd abc abcde);
@tri = sort ({length $b <=> length $a} @tableau);
print "@tri\n";# abcde abcd abc ab a