2012-10-25 5 views
5

Używam funkcji uniq wyeksportowanej przez moduł, List :: MoreUtils, aby znaleźć elementy uniq w tablicy. Jednak chcę, aby znaleźć elementy uniq w sposób niewrażliwy na wielkość liter. Jak mogę to zrobić?Niewrażliwe na przypadki unikalne elementy tablicy w Perlu

Mam dumpingowych wyjście Array przy użyciu danych :: Wywrotka:

#! /usr/bin/perl 

use strict; 
use warnings; 
use Data::Dumper qw(Dumper); 
use List::MoreUtils qw(uniq); 
use feature "say"; 

my @elements=<array is formed here>; 

my @words=uniq @elements; 

say Dumper \@words; 

wyjściowa:

$VAR1 = [ 
      'John', 
      'john', 
      'JohN', 
      'JOHN', 
      'JoHn', 
      'john john' 
     ]; 

Oczekiwany wynik powinien być: John, John John

tylko 2 elementy , rest wszystkie powinny być filtrowane, ponieważ są to te same słowa, na wszelki wypadek jest tylko różnica.

Jak mogę usunąć duplikaty elementów, ignorując przypadek?

Odpowiedz

9

Korzystanie małe, lc z map stwierdzeniem:

my @uniq_no_case = uniq map lc, @elements; 

Powodem List::MoreUtils'uniq jest wielkość liter jest to, że opiera się na charakterystyce deduping z mieszań, który jest również wielkość liter. Kod dla uniq wygląda tak:

sub uniq { 
    my %seen =(); 
    grep { not $seen{$_}++ } @_; 
} 

Jeśli chcesz korzystać z tej sub bezpośrednio w swoim własnym kodzie, można włączyć lc tam:

sub uniq_no_case { 
    my %seen =(); 
    grep { not $seen{$_}++ } map lc, @_; 
} 

wyjaśnienie, jak to działa:

@_ zawiera argumenty podprogramu i są one podawane do instrukcji grep. Wszystkie elementy, które zwracają wartość true po przejściu przez blok kodu, są zwracane przez instrukcję grep. Blok kodu składa się z kilku drobniejszych punktów:

  • $seen{$_}++ zwraca 0 przy pierwszym wyświetleniu elementu. Wartość ta jest wciąż zwiększana do 1, ale po jej zwróceniu (w przeciwieństwie do ++$seen{$_}, która pierwsza przyłączy, a następnie zwróci).
  • Negując wynik inkrementacji, uzyskujemy wartość true dla pierwszego klucza i wartość false dla każdego następnego takiego klucza. Dlatego lista jest odejmowana.
  • grep jako ostatnia instrukcja w podsiebie zwróci listę, która z kolei jest zwracana przez sub.
  • map lc, @_ po prostu stosuje funkcję lc do wszystkich elementów w @_.
+0

A to jest ta sama funkcja uniq eksportowana przez moduł List :: MoreUtils? –

+0

Rzeczywiście tak jest. Chociaż skoro sub jest tak prosty i krótki, możesz po prostu skopiować go i zapisać siebie, ładując moduł. – TLP

+0

Dzięki. Zrozumiem podprocedurę, a następnie wykorzystam ją bezpośrednio :) Czy możesz wyjaśnić trochę składnię grep? Wartość skrótu,% widzi, używa elementów tablicy jako klucza i sprawdza ich występowanie. Ale nie jestem pewien, jak działa ta cała składnia. –

6

Użyj skrótu, aby śledzić słowa, które już widzieliśmy, ale również normalizować ich górna/dolna przypadku:

my %seen; 
my @unique; 
for my $w (@words) { 
    next if $seen{lc($w)}++; 
    push(@unique, $w); 
} 
# @unique has the unique words 

Zauważ, że ten zachowa przypadku oryginalnych słów.

AKTUALIZACJA: Jak wspomniano w komentarzach, nie jest jasne, czego dokładnie potrzebuje PO, ale napisałem rozwiązanie w ten sposób, aby zilustrować ogólną technikę wybierania unikalnych przedstawicieli z listy pod pewną "relacją równoważności". W tym przypadku relacja równoważności to słowo $a jest odpowiednikiem słowa $b tylko wtedy, gdy lc($a) eq lc($b).

Większość równoważne związki mogą być wyrażone w ten sposób, to znaczy, że związek jest określony przez funkcję klasyfikatora f() tak, że $a odpowiada $b wtedy i tylko wtedy, gdy f($a) eq f($b). Na przykład, jeśli chcemy powiedzieć, że dwa słowa są równoważne, jeśli mają tę samą długość, wówczas f() będzie length().

Teraz możesz zobaczyć, dlaczego napisałem algorytm w ten sposób - funkcja klasyfikatora może nie tworzyć wartości, które są częścią oryginalnej listy. W przypadku f = length, chcemy wybrać słowa, ale f słowa jest liczbą.

+0

Używanie 'lc' wewnątrz dostępu hash jest dużo lepsze niż inne rozwiązanie, ponieważ zachowuje on (pierwszy pasujący) przypadek z wejścia. – LeoNerd

+0

@LeoNerd O czym, do licha, mówisz? Nie ma różnicy między używaniem lc przed i wewnątrz hasza. – TLP

+0

Mam na myśli, w przeciwieństwie do mapy lc ... rozwiązanie podane w drugiej odpowiedzi. Ten jest ładniejszy, ponieważ zwraca wartości w oryginalnym przypadku, a nie w trybie wymuszonym - małe litery. – LeoNerd

Powiązane problemy