Hvordan at få unikke elementer af et Perl-list

Opgave. I program i programmeringssproget Perl har en liste. Listen er strenge og tal. Du har brug for at få unikke værdier fra denne liste.

Løsningen ved hjælp af funktionen uniq fra biblioteket List::Util

Den nemmeste og mest bekvemme måde at løse dette problem er at bruge funktion uniq fra biblioteket List::Util. Her er et eksempel kode:

▶ Run
#!/usr/bin/perl

use List::Util qw(uniq);
use Data::Dumper;

my @arr = uniq('one', 'one', 'b', 'one', 'b', 4);

print Dumper \@arr;

Hvis du gemmer denne tekst til en fil script.pl, og derefter udføre i konsollen perl script.pl, det vil blive vist på skærmen:

$VAR1 = [
          'one',
          'b',
          4
        ];

Funktion uniq bevarer rækkefølgen af elementer, og det fungerer korrekt, hvis listen er undef.

Denne kode vil arbejde fra Perl 5.26. I tidligere versioner af Perl indeholder den version af biblioteket List::Util , hvor der ikke er nogen funktion uniq. Så for at for at bruge denne løsning, skal du enten opdatere Perl eller at sætte en nyere version bibliotek List::Util.

Officiel dokumentation

Her er et uddrag af output perldoc List::Util om funktionen uniq:

  uniq
        my @subset = uniq @values

    *Since version 1.45.*

    Filters a list of values to remove subsequent duplicates, as judged by a
    DWIM-ish string equality or "undef" test. Preserves the order of unique
    elements, and retains the first value of any duplicate set.

        my $count = uniq @values

    In scalar context, returns the number of elements that would have been
    returned as a list.

    The "undef" value is treated by this function as distinct from the empty
    string, and no warning will be produced. It is left as-is in the
    returned list. Subsequent "undef" values are still considered identical
    to the first, and will be removed.

Egen beslutning

Lige nok til at skrive en forenklet version af funktionen uniq fra biblioteket List::Util:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

sub uniq {
     my (@values) = @_;

     my %h = map {$_ => 1} @values;

     return keys %h;
}

my @arr = uniq('one', 'one', 'b', 'one', 'b', 4);

print Dumper \@arr;

Denne kode, der umiddelbart virker på alle version af Perl. Her er tre linjer fra subs uniq:

  • my (@values) = @_; — sætte argumenter, der sendes til subwooferen ved en variabel @values
  • my %h = map {$_ => 1} @values; — for hvert element af @values har oprettet en liste med to elementer, den oprindelige element og enhed, og alle de deraf følgende lister sammen i én liste og tildele denne liste til en hash. Et hash er en uordnet række nøgle-værdi. Én nøgle kan kun være én værdi. På grund af denne egenskab af hash fjernet alle dubletter.
  • return keys %h; — returnerede liste består kun af nøgler

Men sammenlignet med den funktion, der uniq fra biblioteket List::Util denne kode har mangler:

  • vores funktion uniq returnerer elementer i vilkårlig rækkefølge. Forskellige kørsler af samme kode føre til forskellige resultater (værdier, der returneres af en funktion, uniq vil være den samme, men den rækkefølge, hvori de er beliggende vil være en andre)
  • vores funktion fungerer ikke korrekt, hvis listen er undef. Vi bruger alle værdier fra den liste, som hash-nøgler. Og undef ikke kan være en nøgle i hash. Når du forsøger at bruge undef som en vigtig og vil blive brugt en tom streng i stedet undef.

Andre artikler