Cum pot elimina elementele duplicate dintr-o matrice din Perl?

Am o matrice în Perl:

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

Cum pot elimina duplicatele din matrice?

0
fr hi bn

9 răspunsuri

Modul meu obișnuit de a face acest lucru este:

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

Dacă utilizați un hash și adăugați elementele la hash. De asemenea, aveți bonusul de a ști de câte ori fiecare element apare în listă.

0
adăugat
Acest lucru are dezavantajul de a nu păstra ordinea inițială, dacă aveți nevoie de ea.
adăugat autor Nathan Fellman, sursa
Este mai bine să utilizați felii în loc de bucla foreach : @unique {@myarray} =()
adăugat autor Onlyjob, sursa

Documentația Perl vine cu o colecție frumoasă de întrebări frecvente. Întrebarea dvs. este frecvent solicitată:

% perldoc -q duplicate

Răspunsul, copiat și lipit de la ieșirea comenzii de mai sus, apare mai jos:

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;
0
adăugat
Ioan iz mah anzers furt mah rep!
adăugat autor brian d foy, sursa
Îmi place că cel mai bun răspuns este 95% copy-paste și 3 propoziții ale OC. Pentru a fi perfect clar, acest este cel mai bun răspuns; Tocmai mi se pare amuzant.
adăugat autor Parthian Shot, sursa
Cred că ar trebui să obțineți puncte bonus pentru a căuta întrebarea.
adăugat autor Brad Gilbert, sursa
adăugat autor szabgab, sursa

Puteți face așa ceva, așa cum este demonstrat în perlfaq4 :

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

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

print "@filtered\n";

ieşiri:

one two three

If you want to use a module, try the uniq function from List::MoreUtils

0
adăugat
De exemplu, dacă ați adăuga o sortare în această funcție, ar fi vorba de $ :: a și $ :: b , nu?
adăugat autor vol7ron, sursa
sub uniq {meu% vazut; grep! $ văzut {$ _} ++, @_} este o implementare mai bună deoarece păstrează ordinea fără costuri. Sau chiar mai bine, utilizați unul din Lista :: Mai multeUtils.
adăugat autor ikegami, sursa
Este un meu lexical în acest domeniu, deci este bine. Acestea fiind spuse, ar putea fi aleasă o denumire variabilă mai descriptivă.
adăugat autor ephemient, sursa
@szabgab, dacă este cazul, este o decizie de proiectare incredibil de rea pentru sort pentru a utiliza variabile non-locale.
adăugat autor Brian Vandenberg, sursa
@ vol7tron înseamnă "înapoi" compatibil, îmi pare rău că a fost bugging-mă ;-)
adăugat autor Tyler, sursa
@BrianVandenberg Bine ați venit în lumea din 1987 - când a fost creată - și aproape 100% combaility backlog pentru perl - deci nu poate fi eliminat.
adăugat autor szabgab, sursa
vă rugăm să nu utilizați $ a sau $ b în exemple, deoarece acestea sunt globale magice de sortare ()
adăugat autor szabgab, sursa

Încercați acest lucru, pare că funcția uniq are nevoie de o listă sortată pentru a funcționa corect.

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";
0
adăugat

Instalați Listați mai multe aplicații din CPAN

Apoi, în codul dvs.:

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);
0
adăugat
@yassinphilip CPAN este unul dintre lucrurile care îl fac pe Perl la fel de puternic și de minunat cum poate fi. Dacă vă scrieți proiectele bazate numai pe modulele de bază, introduceți o limită imensă asupra codului dvs., împreună cu codul scris, care poate încerca să facă ceea ce fac unele module mult mai bine doar pentru a evita utilizarea acestora. De asemenea, utilizarea modulelor de bază nu garantează nimic, deoarece diferite versiuni Perl pot adăuga sau elimina modulele de bază din distribuție, astfel încât portabilitatea este în continuare dependentă de aceasta.
adăugat autor Francisco Zarabozo, sursa
Faptul că Lista :: Mai multeUtils nu este pachet cu perl destul de rău portabilitatea proiectelor care o folosesc :( (I pentru unul nu va)
adăugat autor yPhil, sursa
Acesta este răspunsul! Dar vă pot vota doar o singură dată.
adăugat autor Axeman, sursa
@Ranguard: @dup_list trebuie să fie în interiorul apelului uniq , nu @dups
adăugat autor incutonez, sursa

The variable @array is the list with duplicate elements

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

Se poate face cu un simplu perlină Perl.

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.

Blocul PFM face acest lucru:

Datele din @in sunt introduse în MAP. MAP construiește un hash anonim. Cheile sunt extrase din hash și se alimentează în @out

0
adăugat

Folosind conceptul de chei hash unice:

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

ieşire: a c b d

0
adăugat

Metoda 1: Utilizați un hash

Logică: Un hash poate avea numai chei unice, deci iterați peste matrice, atribuie orice valoare fiecărui element al matricei, păstrând elementul ca cheie a acelui hash. Cheile de întoarcere ale hash-ului, unitatea sa unică.

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

Metoda 2: Extinderea metodei 1 pentru reutilizabilitate

Mai bine să facem o subrutină dacă ar trebui să folosim această funcție de mai multe ori în codul nostru.

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

Method 3: Use module List::MoreUtils

use List::MoreUtils qw(uniq);
my @unique = uniq(@array);
0
adăugat