Question

J'ai un tableau en Perl :

my @my_array = ("one","two","three","two","three");

Comment supprimer les doublons du tableau ?

Était-ce utile?

La solution

Vous pouvez faire quelque chose comme ceci, comme démontré dans perlfaq4:

sub uniq {
    my %seen;
    grep !$seen{$_}++, @_;
}

my @array = qw(one two three two three);
my @filtered = uniq(@array);

print "@filtered\n";

Les sorties:

one two three

Si vous souhaitez utiliser un module, essayez le uniq fonction de List::MoreUtils

Autres conseils

La documentation Perl est livrée avec une belle collection de FAQ.Votre question est fréquemment posée :

% perldoc -q duplicate

La réponse, copiée-collée à partir du résultat de la commande ci-dessus, apparaît ci-dessous :

Found in /usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod
 How can I remove duplicate elements from a list or array?
   (contributed by brian d foy)

   Use a hash. When you think the words "unique" or "duplicated", think
   "hash keys".

   If you don't care about the order of the elements, you could just
   create the hash then extract the keys. It's not important how you
   create that hash: just that you use "keys" to get the unique elements.

       my %hash   = map { $_, 1 } @array;
       # or a hash slice: @hash{ @array } = ();
       # or a foreach: $hash{$_} = 1 foreach ( @array );

       my @unique = keys %hash;

   If you want to use a module, try the "uniq" function from
   "List::MoreUtils". In list context it returns the unique elements,
   preserving their order in the list. In scalar context, it returns the
   number of unique elements.

       use List::MoreUtils qw(uniq);

       my @unique = uniq( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); # 1,2,3,4,5,6,7
       my $unique = uniq( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); # 7

   You can also go through each element and skip the ones you've seen
   before. Use a hash to keep track. The first time the loop sees an
   element, that element has no key in %Seen. The "next" statement creates
   the key and immediately uses its value, which is "undef", so the loop
   continues to the "push" and increments the value for that key. The next
   time the loop sees that same element, its key exists in the hash and
   the value for that key is true (since it's not 0 or "undef"), so the
   next skips that iteration and the loop goes to the next element.

       my @unique = ();
       my %seen   = ();

       foreach my $elem ( @array )
       {
         next if $seen{ $elem }++;
         push @unique, $elem;
       }

   You can write this more briefly using a grep, which does the same
   thing.

       my %seen = ();
       my @unique = grep { ! $seen{ $_ }++ } @array;

Installer Liste ::MoreUtils du CPAN

Puis dans ton code :

use strict;
use warnings;
use List::MoreUtils qw(uniq);

my @dup_list = qw(1 1 1 2 3 4 4);

my @uniq_list = uniq(@dup_list);

Ma façon habituelle de procéder est la suivante :

my %unique = ();
foreach my $item (@myarray)
{
    $unique{$item} ++;
}
my @myuniquearray = keys %unique;

Si vous utilisez un hachage et ajoutez les éléments au hachage.Vous avez également l’avantage de savoir combien de fois chaque élément apparaît dans la liste.

Peut être fait avec un simple Perl One Liner.

my @in=qw(1 3 4  6 2 4  3 2 6  3 2 3 4 4 3 2 5 5 32 3); #Sample data 
my @out=keys %{{ map{$_=>1}@in}}; # Perform PFM
print join ' ', sort{$a<=>$b} @out;# Print data back out sorted and in order.

Le bloc PFM fait ceci :

Les données dans @in sont introduites dans MAP.MAP crée un hachage anonyme.Les clés sont extraites du hachage et introduites dans @out

La variable @array est la liste des éléments en double

%seen=();
@unique = grep { ! $seen{$_} ++ } @array;

Ce dernier était plutôt bon.Je voudrais juste le modifier un peu :

my @arr;
my @uniqarr;

foreach my $var ( @arr ){
  if ( ! grep( /$var/, @uniqarr ) ){
     push( @uniqarr, $var );
  }
}

Je pense que c'est probablement la façon la plus lisible de procéder.

Méthode 1 :Utiliser un hachage

Logique:Un hachage ne peut avoir que des clés uniques, alors parcourez le tableau, attribuez n'importe quelle valeur à chaque élément du tableau, en conservant l'élément comme clé de ce hachage.Renvoie les clés du hachage, c'est votre tableau unique.

my @unique = keys {map {$_ => 1} @array};

Méthode 2 :Extension de la méthode 1 pour la réutilisabilité

Mieux vaut créer un sous-programme si nous sommes censés utiliser cette fonctionnalité plusieurs fois dans notre code.

sub get_unique {
    my %seen;
    grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);

Méthode 3 :Utiliser le module List::MoreUtils

use List::MoreUtils qw(uniq);
my @unique = uniq(@array);

Les réponses précédentes résument assez bien les moyens possibles d’accomplir cette tâche.

Cependant, je suggère une modification pour ceux qui ne le faites pas se soucier de compte les doublons, mais faire se soucier de l'ordre.

my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;

Notez que le suggéré précédemment grep !$seen{$_}++ ... incréments $seen{$_} avant la négation, donc l'incrément se produit indépendamment du fait qu'il ait déjà été %seen ou non.Cependant, ce qui précède provoque des courts-circuits lorsque $record{$_} est vrai, laissant ce qui a été entendu une fois hors du %record'.

On pourrait aussi opter pour ce ridicule, qui profite de l'autovivification et de l'existence de clés de hachage :

...
grep !(exists $record{$_} || undef $record{$_}), @record;

Cela pourrait toutefois prêter à confusion.

Et si vous ne vous souciez ni de l'ordre ni du nombre de doublons, vous pouvez effectuer un autre hack en utilisant des tranches de hachage et l'astuce que je viens de mentionner :

...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped

Essayez ceci, il semble que la fonction uniq ait besoin d'une liste triée pour fonctionner correctement.

use strict;

# Helper function to remove duplicates in a list.
sub uniq {
  my %seen;
  grep !$seen{$_}++, @_;
}

my @teststrings = ("one", "two", "three", "one");

my @filtered = uniq @teststrings;
print "uniq: @filtered\n";
my @sorted = sort @teststrings;
print "sort: @sorted\n";
my @sortedfiltered = uniq sort @teststrings;
print "uniq sort : @sortedfiltered\n";

Utilisation du concept de clés de hachage uniques :

my @array  = ("a","b","c","b","a","d","c","a","d");
my %hash   = map { $_ => 1 } @array;
my @unique = keys %hash;
print "@unique","\n";

Sortir:un c b d

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top