2012-10-25 15 views
5

Sto utilizzando la funzione uniq esportata dal modulo, List :: MoreUtils per trovare gli elementi uniq in una matrice. Tuttavia, voglio che trovi gli elementi di uniq in un modo maiuscole e minuscole. Come lo posso fare?Elementi di matrice univoca maiuscole/minuscole in Perl

ho scaricato l'uscita del Array utilizzando Data :: Dumper:

#! /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; 

uscita:

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

output previsto dovrebbe essere: John, John John

Solo 2 elementi , tutto il resto dovrebbe essere filtrato poiché sono la stessa parola, solo la differenza è nel caso.

Come posso rimuovere gli elementi duplicati ignorando il caso?

risposta

9

Usa minuscole, lc con una dichiarazione map:

my @uniq_no_case = uniq map lc, @elements; 

La ragione List::MoreUtils'uniq è case sensitive è che si basa sulle caratteristiche deduping di hash, che è anche tra maiuscole e minuscole. Il codice per uniq assomiglia così:

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

Se si desidera utilizzare questo sub direttamente nel proprio codice, si potrebbe integrare lc in là:

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

spiegazione di come funziona:

@_ contiene gli argomenti della subroutine e vengono inviati a una dichiarazione grep. Qualsiasi elemento che restituisce true quando viene passato attraverso il blocco di codice viene restituito dall'istruzione grep. Il blocco di codice è costituito da alcuni punti più sottili:

  • $seen{$_}++ restituisce 0 la prima volta che viene visualizzato un elemento. Il valore è ancora incrementato a 1, ma dopo che è stato restituito (al contrario di ++$seen{$_} chi avrebbe incuito prima, quindi restituisce).
  • Negando il risultato dell'incremento, si ottiene true per la prima chiave e false per ogni seguente chiave. Quindi, l'elenco è deduplicato.
  • grep come ultima dichiarazione nel sottotitolo restituirà un elenco, che a sua volta viene restituito dal sub.
  • map lc, @_ applica semplicemente la funzione lc a tutti gli elementi in @_.
+0

E questa è la stessa funzione uniq esportata dal modulo List :: MoreUtils? –

+0

In effetti lo è. Anche se il sub è così semplice e breve, puoi semplicemente copiarlo incollandolo e salvarti caricando il modulo. – TLP

+0

Grazie. Capirò la subroutine e poi la userò direttamente :) Puoi spiegare un po 'la sintassi grep? L'hash,% seen sta usando gli elementi dell'array come chiave e controllandone l'occorrenza. Ma, non sono sicuro, come funziona questa intera sintassi. –

6

Utilizzare un hash per tenere traccia delle parole che hai già visto, ma anche normalizzare la loro per/minuscole superiore:

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

Si noti che questo conserverà il caso delle parole originali.

AGGIORNAMENTO: Come notato nei commenti, non è chiaro esattamente di cosa l'OP abbia bisogno, ma ho scritto la soluzione in questo modo per illustrare una tecnica generale per selezionare rappresentanti univoci da una lista sotto qualche "relazione di equivalenza". In questo caso la relazione di equivalenza è la parola $a equivale alla parola $b se e solo se lc($a) eq lc($b).

maggior parte dei rapporti di equivalenza possono essere espresse in questo modo, cioè, il rapporto è definito da una funzione di classificazione f() tale che $a è equivalente a $b se e solo se f($a) eq f($b). Ad esempio, se vogliamo dire che due parole sono equivalenti se hanno la stessa lunghezza, allora f() sarebbe length().

Così ora si potrebbe vedere perché ho scritto l'algoritmo in questo modo - la funzione di classificazione non può produrre valori che fanno parte dell'elenco originale. Nel caso di f = length, vogliamo selezionare le parole, ma f di una parola è un numero.

+0

L'uso di 'lc' all'interno dell'accesso ad hash è molto più bello dell'altra soluzione data, poiché conserva il caso (primo corrispondente) dall'input. – LeoNerd

+0

@LeoNerd Di che diavolo stai parlando? Non c'è differenza tra l'uso di lc prima e all'interno dell'hash. – TLP

+0

Intendevo, al contrario della mappa lc ... soluzione data nell'altra risposta. Questo è più bello in quanto restituisce valori nel loro caso originale, non in maiuscolo. – LeoNerd

Problemi correlati