Suppression des doublons dans un tableau des chaines des caractères

Suppression des doublons dans un tableau des chaines des caractères - Perl - Programmation

Marsh Posté le 20-02-2013 à 19:29:24    

Bonjour à tous ,  
 
J'ai un fichier dont chaque ligne contient un mot, j'ai récupéré le contenu de ce fichier dans un tableau et j'ai essayé de supprimer les doublons , j'ai essayé ce code mais toujours il y a des problèmes  
voilà le code :
 
 @Ti = <F>;
 
 my @unique = ();
  my %dejavu = ();
 
  foreach my $elem ( @Ti )
    {
  chomp(@Ti);
      next if $dejavu{ $elem }++;
      push @unique, $elem;
    }
 
 
 
 
foreach my $val ( @unique ) {
 
 
 print FIC "$val\n";  
 }

Reply

Marsh Posté le 20-02-2013 à 19:29:24   

Reply

Marsh Posté le 20-02-2013 à 19:45:25    

chomp(@Ti);  [:what has been seen]  
c'est chomp  $elem; que tu voulais faire je suppose.
 
Pour le reste, le code a l'air OK, et sinon, il y a
use List::MoreUtils  qw{uniq};
 
A+,


Message édité par gilou le 20-02-2013 à 19:45:50

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 21-02-2013 à 11:27:11    

Bonjour,  
alors comment utiliser use List::MoreUtils  qw{uniq};  ??

Reply

Marsh Posté le 21-02-2013 à 11:50:48    

:hello: Bonjour,
 
use List::MoreUtils  qw{uniq};
 
my @array;
........
@array = uniq(@array);  # ou my @unique = uniq(@array); si on veut conserver @array tel quel
 
Bon bien sur, List::MoreUtils n'étant pas un module de base, il faut l'avoir ajouté à sa configuration avec ppm, cpan ou autre. En fait, je crois qu'on peut même l'installer directement comme fichier car il n'a pas de dépendances.
 
Sinon, il y a la technique universelle,
my @array;
......
my %seen;
my @unique = grep { ! $seen{$_}++ } @array;
 
ou copier directement dans son code celui de List::MoreUtils, qui utilise cette technique:
 
sub uniq (@) {
    my %seen = ();
    grep { not $seen{$_}++ } @_;
}
 
A+,


Message édité par gilou le 21-02-2013 à 11:58:23

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 21-02-2013 à 19:02:39    

SVP commet ajouter le module  List::MoreUtils ???

Reply

Marsh Posté le 21-02-2013 à 19:20:57    

Euh, vu que vous avez besoin que de uniq, je ne vois pas pourquoi vous ne faites pas comme je vous ai indiqué.

Citation :

ou copier directement dans son code celui de List::MoreUtils, qui utilise cette technique:  
 
sub uniq (@) {  
    my %seen = ();  
    grep { not $seen{$_}++ } @_;  
}


 
Sinon, pour l'ajouter à votre système, ça dépend de la configuration de votre système, ça peut être fait avec ppm (pour une distribution active perl) ou cpan (pour une distribution strawberry perl ou une distribution linux)
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-02-2013 à 12:54:05    

j'ai essayé ce code mais il y a un problème que j'arrive pas à le résoudre en fait mon fichier d'entré contient les lignes suivants :
bonjour
bonsoir
bonsoir
madame
bonjour
madame
 
et voila la sortie de programme :
madame
bonsoir
bonjour
bonjour
 
je pas réussi à savoir pourquoi il y a ajout des caractères au mot bonjour et comment résoudre ce problème ??

Reply

Marsh Posté le 22-02-2013 à 14:11:28    

Chez moi ça marche.

Code :
  1. #!/usr/bin/perl
  2. use v5.10.1;
  3. # code propre
  4. use strict;
  5. use warnings;
  6. use autodie;
  7. # uniq de List::MoreUtils
  8. sub uniq (@) {
  9.    my %seen = ();
  10.    grep { not $seen{$_}++ } @_;
  11. }
  12. # lecture des données dans un array
  13. open my $fh, "< enis.txt";
  14. my @a = <$fh>;
  15. close $fh;
  16. # on vire le \n final et les blancs de début et fin de ligne
  17. map {chomp; s/(^\s*|\s*$)//g} @a;
  18. # on vire les doublons
  19. @a = uniq @a;
  20. # On imprime chaque ligne
  21. map {say} @a;


C:\Perl>perl enis.pl
bonjour
bonsoir
madame


A+,


Message édité par gilou le 22-02-2013 à 14:14:21

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-02-2013 à 14:43:05    

Citation :

bonjour

Manifestement, tu n'es pas en encodage ansi, mais en unicode, et il faut en tenir compte:
....
close $fh;
my $line = shift @a;
$line =~ s/^\x{ef}\x{bb}\x{bf}//; #retire la BOM UTF-8 de début de fichier
unshift @a, $line;

map {chomp; s/(^\s*|\s*$)//g} @a;
....
 
Bon, je suis sur la route maintenant, donc pas de réponse avant ce soir.
A+,


Message édité par gilou le 22-02-2013 à 17:51:54

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-02-2013 à 18:52:21    

Merci beaucoup gilou pour votre aide , j'ai essayé le code et c'est bien marché sauf que je veux pas perdre l'ordre des mots ... Avez vous une solution ???

Reply

Marsh Posté le 22-02-2013 à 18:52:21   

Reply

Marsh Posté le 22-02-2013 à 18:58:29    

L'ordre des mots n'est pas perdu, comme vous l'indiquait ma réponse:

C:\Perl>perl enis.pl  
bonjour  
bonsoir  
madame


a partir de:  
-----------------------------
bonjour
bonsoir
bonsoir  
madame
bonjour  
madame  
------------------------------
On voit bien que seule la première occurrence est conservée, dans son ordre d'apparition.
 
A+,


Message édité par gilou le 22-02-2013 à 18:59:38

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-02-2013 à 19:05:44    

Moi j'ai utilisé ce code :  
 
 
open(F,'E:\\Mastère_2013\\Script\\IN6.txt') or die ("Erreur d'ouverture " ) ;
 
open(FIC,'>E:\\Mastère_2013\\Script\\OUT.txt') or die ("Erreur de creation " ) ;
 
@Ti = <F>;
close F;
my $line = shift @Ti;  
$line =~ s/^\x{ef}\x{bb}\x{bf}//; #retire la BOM UTF-8 de début de fichier  
unshift @Ti, $line;  
map {chomp; s/(^\s*|\s*$)//g} @Ti;  
 
my %dejavu;
 
foreach my $elem ( @Ti )
{
     $dejavu{$elem} = 1;
}
#print $_ , "\n" foreach keys %dejavu
 
print FIC $_ , "\n" foreach keys %dejavu
 
le fichier d'entré contient :  
Bonjour
Bonsoir
Madame
Bonjour
Rania
Amine
Amine
 
Alors la sortie est la suivante :  
Bonsoir
Rania
Amine
Bonjour
Madame

 Moi je veux qu'il m'affiche :  
Bonjour
Bonsoir
Madame
Rania
Amine

 
 
 
 
 

Reply

Marsh Posté le 22-02-2013 à 19:34:35    

C'est pas une mauvaise idée à la base, sauf que ça ne peut pas marcher parce qu'un hash ne range pas les clés dans leur ordre d'apparition  (et que de plus, pour des raisons de sécurité, l'ordre est systématiquement variable depuis une des toutes dernières versions de perl).
 
A+,


Message édité par gilou le 22-02-2013 à 19:35:07

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-02-2013 à 19:49:24    

Bonsoir ,  
J'ai changé un peu le code et normalement c'est bien marché voilà la solution finale  
 
open(F,'E:\\Mastère_2013\\Script_Final\\IN.txt') or die ("Erreur d'ouverture " ) ;
 
open(FIC,'>E:\\Mastère_2013\\Script_Final\\OUT.txt') or die ("Erreur de creation " ) ;
 
@Ti = <F>;
close F;
my $line = shift @Ti;  
$line =~ s/^\x{ef}\x{bb}\x{bf}//; #retire la BOM UTF-8 de début de fichier  
unshift @Ti, $line;  
map {chomp; s/(^\s*|\s*$)//g} @Ti;  
 
my %dejavu;
my @unique = ();  
 
foreach my $elem ( @Ti )
{
     #$dejavu{$elem} = 1;
  next if $dejavu{ $elem }++;  
      push @unique, $elem;  
}
#print $_ , "\n" foreach keys %dejavu
 
#print FIC $_ , "\n" foreach keys %dejavu
foreach my $val ( @unique ) {
 print FIC "$val\n";  
 }
 
j'ai essayé votre code  

Code :
  1. #!/usr/bin/perl
  2. use v5.10.1;
  3. # code propre
  4. use strict;
  5. use warnings;
  6. use autodie;
  7. # uniq de List::MoreUtils
  8. sub uniq (@) {
  9.     my %seen = ();
  10.     grep { not $seen{$_}++ } @_;
  11. }
  12. # lecture des données dans un array
  13. open my $fh, "< enis.txt";
  14. my @a = <$fh>;
  15. close $fh;
  16. # on vire le \n final et les blancs de début et fin de ligne
  17. map {chomp; s/(^\s*|\s*$)//g} @a;
  18. # on vire les doublons
  19. @a = uniq @a;
  20. # On imprime chaque ligne
  21. map {say} @a;


 
mais il y a des erreurs , dans tous les cas je suis très reconnaissante d'avoir m'aider , merci beaucoup :)

Reply

Marsh Posté le 22-02-2013 à 20:56:49    

rim_enis a écrit :

Bonsoir ,  
j'ai essayé votre code  

Code :
  1. #!/usr/bin/perl
  2. use v5.10.1;
  3. # code propre
  4. use strict;
  5. use warnings;
  6. use autodie;
  7. # uniq de List::MoreUtils
  8. sub uniq (@) {
  9.    my %seen = ();
  10.    grep { not $seen{$_}++ } @_;
  11. }
  12. # lecture des données dans un array
  13. open my $fh, "< enis.txt";
  14. my @a = <$fh>;
  15. close $fh;
  16. # on vire le \n final et les blancs de début et fin de ligne
  17. map {chomp; s/(^\s*|\s*$)//g} @a;
  18. # on vire les doublons
  19. @a = uniq @a;
  20. # On imprime chaque ligne
  21. map {say} @a;


 
mais il y a des erreurs , dans tous les cas je suis très reconnaissante d'avoir m'aider , merci beaucoup :)

Non, il n'y a pas d'erreurs (c'est du code particulièrement simple) si vous remplacez le nom du fichier correctement (enis.txt -> E:\\Mastère_2013\\Script_Final\\IN.txt) et si vous avez un perl récent (v5.16 par exemple)
 
Par contre, il y en a dans votre code:
> open(F,'E:\\Mastère_2013\\Script_Final\\IN.txt') or die ("Erreur d'ouverture " ) ;  
Non, c'est
open(F,'E:\Mastère_2013\Script_Final\IN.txt') or die ("Erreur d'ouverture " ) ;  
ou bien
open(F,"E:\\Mastère_2013\\Script_Final\\IN.txt" ) or die ("Erreur d'ouverture " ) ;  
Si vous utilisez les " " pour les chaines, il faut \\, mais si vous utilisez ' ', alors il faut \ et non pas \\.
 
Il manque un close FIC; final.
D'autre part, vous utilisez des globs pour les filehandlers (F, FIC), ce qui marche, mais est loin d'être très moderne comme approche.
 
> open(F,'E:\\Mastère_2013\\Script_Final\\IN.txt') or die ("Erreur d'ouverture " )
l'utilisation de  
use autodie;  
rend la partie avec die(...) superflue, et devrait être standard dans tout code perl moderne.
D'autre part, vous n'indiquez pas explicitement que c'est une ouverture en lecture seulement.
 
>open(FIC,'>E:\\Mastère_2013\\Script_Final\\OUT.txt') or die ("Erreur de creation " ) ;
ça ne sert a rien d'ouvrir un fichier qu'on n'utilise pas immédiatement ensuite.  
 
Enfin, il faut être cohérent dans le style, et choisir entre
open(F,...); et close(F);
ou
open F, ...; et close F;
Mais pas un mélange des deux styles.
 
enfin, utilisez systématiquement des variables locales:
my @Ti = <...>; et non pas @Ti = <...>;
 
Donc dans un premier temps, votre code devrait ressembler à ceci:

Code :
  1. #!/usr/bin/perl
  2. use v5.10.1;
  3. # code propre
  4. use strict;
  5. use warnings;
  6. use autodie;
  7.  
  8. open(F, "< E:\\Mastère_2013\\Script_Final\\IN.txt" );
  9. my @Ti = <F>;
  10. close(F);
  11.  
  12. my $line = shift @Ti;
  13. $line =~ s/^\x{ef}\x{bb}\x{bf}//; #retire la BOM UTF-8 de début de fichier
  14. unshift @Ti, $line;
  15. map {chomp; s/(^\s*|\s*$)//g} @Ti;
  16.  
  17. my %dejavu;
  18. my @unique = ();
  19.  
  20. foreach my $elem ( @Ti )
  21. {
  22.  next if $dejavu{ $elem }++;
  23.  push @unique, $elem;
  24. }
  25.  
  26. open(FIC, "> E:\\Mastère_2013\\Script_Final\\OUT.txt" );
  27. foreach my $val ( @unique ) {
  28.  print FIC "$val\n";
  29. }
  30. close(FIC);


 
et c'est améliorable:

Code :
  1. #!/usr/bin/perl
  2. use v5.10.1;
  3. # code propre
  4. use strict;
  5. use warnings;
  6. use autodie;
  7.  
  8. open(F, "< E:\\Mastère_2013\\Script_Final\\IN.txt" );
  9. my @Ti = <F>;
  10. close(F);
  11.  
  12. my $line = shift @Ti;
  13. $line =~ s/^\x{ef}\x{bb}\x{bf}//; #retire la BOM UTF-8 de début de fichier
  14. unshift @Ti, $line;
  15. map {chomp; s/(^\s*|\s*$)//g} @Ti;
  16.  
  17. my (%dejavu, @unique);
  18. map {push @unique, $_ unless $dejavu{ $_ }++} @Ti;
  19.  
  20. open(FIC, "> E:\\Mastère_2013\\Script_Final\\OUT.txt" );
  21. map {print FIC "$_\n"} @unique;
  22. close(FIC);


 
A+,
 
 
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 23-02-2013 à 16:47:41    

Bonsoir
j'ai toujours un problème avec use autodie;

Reply

Marsh Posté le 23-02-2013 à 17:53:19    

Parce que vous n'avez pas une version ou le module autodie est installé par défaut, c'est bizarre, parce que ce devrait être le cas a partir de la version  v5.10.1, c'est même pour cela que j'ai mis exprès use  v5.10.1; avant.
 
Quand vous faites perl -v, ça vous donne quoi comme numéro de version?
 
A+,


Message édité par gilou le 23-02-2013 à 17:54:18

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 28-02-2013 à 19:51:18    

Bonjour,  
C'est la version 5.6.1 :)

Reply

Marsh Posté le 28-02-2013 à 21:51:51    

Donc c'est pour cela. Faut vivre avec son temps, la version que vous utilisez date de plus de 12 ans.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed