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 !


SommaireCodes sources utilesDes codes sourcesGestions des tableaux (Array) (3)
précédent sommaire suivant
 

Il existe différentes méthodes pour supprimer les doublons dans une liste (un tableau) en perl. La première méthode consiste à utiliser un module Perl. C'est bien évidemment la méthode la plus recommandée car les modules disponibles sur le CPAN sont efficaces et bien écrits.
Voici une liste de modules intéressants :


La seconde méthode revient à ne pas utiliser de modules et coder soit même. Voici 3 procédures élégantes qui permettent de supprimer les doublons d'un tableau. Comparons les.

  • Technique 1 (hash anonyme)

Cette procédure prend en argument une référence d'un tableau et chaque case du tableau devient une clé d'un hash anonyme. Les clés de la table de hachage sont renvoyées.

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
#!/usr/bin/perl 
use strict; 
use warnings; 
  
sub doublons_hash_anonyme { 
  my ($ref_tabeau) = @_; 
  
  return keys %{ { map { $_ => 1 } @{$ref_tabeau} } }; 
}
  • Technique 2 (tranche)

Cette procédure prend en argument une référence d'un tableau et chaque case du tableau devient la clé d'une tranche de hachage d'un hachage qu'on aura déclaré.

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/perl 
use strict; 
use warnings; 
  
sub doublons_tranche { 
  my ($ref_tabeau) = @_; 
  
  my %hash_sans_doublon;    # Comme un hash ne peut pas avoir deux clés identiques, 
                            # utilser ces clé permet d'avoir un tableau unique 
  @hash_sans_doublon{ @{$ref_tabeau} } = ();    # Pas besoin de surcharger le hash avec des valeurs inutiles 
                                                # et ensuite, on renvoie le tableau des clés uniques 
  return keys %hash_sans_doublon; 
}
  • Technique 3 (grep)

Cette procédure prend en argument une référence d'un tableau et chaque case est passée au filtre grep qui ne conserve que celles qui n'ont pas déjà été vues.

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl 
use strict; 
use warnings; 
  
sub doublons_grep { 
  my ($ref_tabeau) = @_; 
  
  my %hash_sans_doublon; 
  
  return grep { !$hash_sans_doublon{$_}++ } @{$ref_tabeau}; 
}
  • Avantages et inconvénients

Ces trois techniques sont simples, efficaces et facilement maintenables. Il n'est pas du tout nécessaire d'installer un nouveau module pour cela, bien que List::Util soit dans le CORE de perl depuis sa version 5.8.
Pour de plus amples manipulations de tableaux, je vois recommande biensûr les modules cités ci-dessus.

Sachez maintenant que parmi ces 3 procédures, certaines sont plus rapides que d'autres. la technique 2 (à coup de tranche) est la plus rapide des 3, ensuite vient la technique 3 (à coup de grep), puis vient la dernière (technique 1). Ce n'est qu'une remarque, mais tout dépend de la longueur des listes, du nombre de doublons qu'elles contiennent, etc ... En général, la première place est toujours partagée entre la technique 2 (à coup de tranche) et 3 (à coup de grep).

Autres remarques :
- La technique 2 (tranche) est plus avantageuse que la 1 car elle n'a pas besoin de créer une liste intermédiaire.
- Notez bien que seule la technique 3 ( grep) permet de conserver l'ordre des éléments du tableau après suppression des doublons (important selon vos besoins) ! Sachez que la différence de temps entre la 2 et 3 n'est pas non plus dramatique. Utilisez le module Benchmark pour effectuer vos tests si vous le souhaitez.

  • Exemple d'utilisation

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
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/perl 
use strict; 
use warnings; 
  
my @listing_mots = qw/ moi 2Eurocents Woufeil toi djibril Jedai moi Jedai gldavid 
  etc Jedai Stoyak lui nous tous je tu elle lui perl 10 20 20 30 8 6 9 100 
  /; 
  
my @resultat1 = doublons_hash_ano( \@listing_mots ); 
my @resultat2 = doublons_tranche( \@listing_mots ); 
my @resultat3 = doublons_grep( \@listing_mots ); 
  
print "Original : @listing_mots\n"; 
print "HASH anonyme : @resultat1\n"; 
print "Tranche : @resultat2\n"; 
print "GREP : @resultat3\n"; 
  
sub doublons_hash_anonyme { 
  my ($ref_tabeau) = @_; 
  
  return keys %{ { map { $_ => 1 } @{$ref_tabeau} } }; 
} 
  
sub doublons_grep { 
  my ($ref_tabeau) = @_; 
  
  my %hash_sans_doublon; 
  
  return grep { !$hash_sans_doublon{$_}++ } @{$ref_tabeau}; 
} 
  
sub doublons_tranche { 
  my ($ref_tabeau) = @_; 
  
  my %hash_sans_doublon;    # Comme un hash ne peut pas avoir deux clés identiques, 
                            # utilser ces clé permet d'avoir un tableau unique 
  @hash_sans_doublon{ @{$ref_tabeau} } = ();    # Pas besoin de surcharger le hash avec des valeurs inutiles 
                                                # et ensuite, on renvoie le tableau des clés uniques 
  return keys %hash_sans_doublon; 
} 
  
sub doublons_hash_ano { 
  my ($ref_tabeau) = @_; 
  
  return keys %{ { map { $_ => 1 } @{$ref_tabeau} } }; 
}
Code : Sélectionner tout
1
2
3
4
Original : moi 2Eurocents Woufeil toi djibril Jedai moi Jedai gldavid etc Jedai Stoyak lui nous tous je tu elle lui perl 10 20 20 30 8 6 9 100 
HASH anonyme : djibril toi je gldavid etc tu Woufeil 30 100 moi 6 Jedai 9 20 8 2Eurocents perl tous lui Stoyak elle 10 nous 
Tranche : djibril toi je gldavid etc tu Woufeil 30 100 moi 6 Jedai 9 20 8 2Eurocents perl tous lui Stoyak elle 10 nous 
GREP : moi 2Eurocents Woufeil toi djibril Jedai gldavid etc Stoyak lui nous tous je tu elle perl 10 20 30 8 6 9 100
On peut constater que l'ordre est conservé pour la technique 3. Voilà, à vos tests. :-) !!

Mis à jour le 5 décembre 2008 djibril

La fonction sort() en Perl est très puissante et permet de faire tous les tris inimaginables.
Elle trie les éléments d'une liste et retourne une liste triée des éléments fournis en paramètre.
Ces deux listes peuvent être distinctes, ou bien la liste d'origine peut être écrasée par le résultat du tri si elle est destinataire de l'affectation.
La fonction sort peut prendre un argument spécial qui est le bloc de comparaison à effectuer entre les éléments de la liste à trier. Il est ainsi possible de trier selon des critères tout à fait personnalisés.
Par défaut, le tri se fait dans l'ordre "lexicographique" (ordre alphabétique, étendu aux nombres dont les chiffres sont traités comme des caractères et non comme des nombres). Le bloc de comparaison personnalisé doit être précisé entre accolades, avant la liste d'éléments à trier, sans être séparé de celle-ci par une virgule. Pour la comparaison, ce bloc utilise deux variables internes de PERL, $a et $b, qui ne sont définies que dans ce bloc et masquent toute variable $a ou $b propre à l'utilisateur. Ce bloc effectue donc un test quelconque, basé sur $a et $b, dont le résultat peut prendre trois valeurs :

  • positif si $a est avant $b dans l'ordre de tri souhaité ;
  • nul si $a et $b sont équivalents ;
  • négatif si $a est après $b dans l'ordre souhaité.

Ces trois valeurs de résultat de test correspondent aux résultats des opérateurs de test et cmp vus précédemment.
Ainsi, pour un tri lexicographique du tableau @t, on peut faire :

Code perl : Sélectionner tout
@l = sort ( @t ); ou bien @l = sort ( { $a cmp $b } @t );
qui a l'avantage d'être totalement explicite et donc plus clair à maintenir.
Pour un tri lexicographique inversé, on peut aussi bien écrire :

Code perl : Sélectionner tout
@l = reverse ( sort ( { $a cmp $b } @t ) );
que

Code perl : Sélectionner tout
@l = sort ( { $b cmp $a } @t );
Mais sachez que reverse est beaucoup plus optimal que faire sort ( { $b cmp $a } @t.
Pour un tri numérique :

Code perl : Sélectionner tout
@l = sort ( { $a <=> $b } @t );
Pour un tri un peu spécial, en supposant que @t contienne des indices d'un tableau et que l'on souhaite un tri de ces indices selon les valeurs numériques du tableau :

Code perl : Sélectionner tout
@l = sort ( { $tableau[$a] <=> $tableau[$b] } @t );
@l contient alors les valeurs de @t triées dans un ordre tel qu'elles indicent des valeurs croissantes dans @tableau. C'est très indirect et ce n'est pas forcément très naturel au début, mais c'est extrêmement puissant. Et pour finir, bien que l'on ait pas encore abordé la définition de fonctions personnalisées, il est possible d'appeler une fonction définie par le programmeur :

Code perl : Sélectionner tout
@l = sort ( { mafonction ($a, $b) } @t );
Nous vous recommandons de lire les articles ci dessous

les mongueurs de Perl (groupe francophone consacré à la promotion de Perl) ont écrit un très bon article.
En voici d'autres :

Mis à jour le 5 décembre 2008 2Eurocents

Il arrive que l'on ait besoin de comparer 2 listes perl entre elles afin d'obtenir les données communes aux deux listes, les données présentes dans une liste mais pas dans l'autre ... Pas besoin de reinventer la roue, il existe un module sur le CPAN qui le fait très bien, c'est List::Compare. Voici un exemple de code :

Code perl : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/perl 
use strict; 
use warnings; 
use List::Compare; 
  
my @Llist = qw(abel abel baker camera delta edward fargo golfer); 
my @Rlist = qw(baker camera delta delta edward fargo golfer hilton); 
  
my $lc = List::Compare->new( \@Llist, \@Rlist ); 
  
my @intersection = $lc->get_intersection; 
my @union        = $lc->get_union; 
  
print "@intersection\n@union\n"; 
# baker camera delta edward fargo golfer 
# abel baker camera delta edward fargo golfer hilton

Mis à jour le 6 janvier 2011 djibril

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 -