Jak uzyskać unikalne elementy z listy Perl

Zadanie. W programie w języku programowania Perl jest lista. W liście wiersze i liczby. Trzeba uzyskać unikatowe wartości z tej listy.

Rozwiązanie za pomocą funkcji uniq z biblioteki List::Util

Najprostszy i najbardziej wygodny sposób, aby rozwiązać to zadanie to wykorzystać funkcję uniq z biblioteki List::Util. Oto przykład kodu:

▶ Run
#!/usr/bin/perl

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

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

print Dumper \@arr;

Jeżeli zapisz ten tekst w plik script.pl, a potem wykonać w konsoli perl script.pl, na ekranie pojawi się:

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

Funkcja uniq zachowuje kolejność elementów i ona działa poprawnie jeśli na liście znajduje się undef.

Ten kod będzie działać od wersji Perl 5.26. W starszych wersjach Perl zawiera wersja biblioteki List::Util , w którym nie ma jeszcze funkcji uniq. Tak aby korzystać z tego rozwiązania trzeba albo zaktualizować Perl, albo umieścić nowszą wersję biblioteki List::Util.

Oficjalna dokumentacja

Oto fragment danych wyjściowych polecenia perldoc List::Util o funkcję 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.

Własne rozwiązanie

Wystarczy napisać uproszczony wariant funkcji uniq z biblioteki 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;

Ten kod od razu działa na każdej wersji Perl. Oto trzy linijki z saby uniq:

  • my (@values) = @_; — złożył argumenty, które przekazane w sabu w zmiennej @values
  • my %h = map {$_ => 1} @values; — dla każdego elementu z @values stworzyliśmy listę z dwóch elementów — pierwszy element i jednostka, i wszystkie otrzymane listy połączyli w jedną listę i nadano ta lista хешу. Hesh — to неупорядоченный zestaw par klucz-wartość. Według jednego klucza może być tylko jedna wartość. Dzięki tej właściwości mieszania są usuwane wszystkie ujęcia.
  • return keys %h; — zwróćcie lista składa się tylko z kluczy mieszania

Ale w porównaniu z funkcją uniq z biblioteki List::Util u tego kodu jest wady:

  • nasza funkcja uniq zwraca elementy w dowolnej kolejności. Różne starty jednego i tego samego kodu prowadzić do różnych wyników (wartości które zwraca funkcja uniq będą te same, ale oto kolejność w jakiej znajdują się one będzie się różnić).
  • nasza funkcja działa poprawnie jeśli na liście znajduje się undef. Wykorzystujemy wszystkie wartości z listy jako kluczy mieszania. A undef nie może być kluczem w хеше. Podczas próby użycia undef jako klucz będzie ostrzeżenie i będzie wykorzystana na pusty ciąg znaków zamiast undef.

Inne artykuły