2013-09-06 14 views
6

Ho un hash di hash che devo filtrare. Ho trovato come fare una ricerca ma non ha risposto alla mia domanda.Filtrare un hash di hash in perl

dire che ho un hash di hash così:

my %HoH = (
    flintstones => { 
     husband => "fred", 
     pal  => "barney", 
     town  => "springfield" 
    }, 
    jetsons => { 
     husband => "george", 
     wife  => "jane", 
     "his boy" => "elroy", 
    }, 
    simpsons => { 
     husband => "homer", 
     wife  => "marge", 
     kid  => "bart", 
     town  => "springfield", 
    }, 
); 

mi consente di dire che voglio tutti i townfolks da Springfield. Voglio lo stesso hash di hash in uscita senza gli outsider.

my %HoH = (
    flintstones => { 
     husband => "fred", 
     pal  => "barney", 
     town  => "springfield" 
    }, 
    simpsons => { 
     husband => "homer", 
     wife  => "marge", 
     kid  => "bart", 
     town  => "springfield", 
    }, 
); 

Sembra sciocco ma non riesce a capire come filtrare il puntone. L'obiettivo sarebbe quello di iterare su tutte le persone di Springfield dopo il filtraggio.

Naturalmente ho fatto delle ricerche e la cosa più vicina che ho trovato sono le hash slice. Ma sembrano spaventosi.

risposta

10

Innanzitutto è necessario trovare le chiavi degli elementi che si desidera rimuovere:

grep { $HoH{$_}{town} eq 'springfield' } keys(%HoH) 

Poi non vengono eliminati:

delete $HoH{$_} for grep { $HoH{$_}{town} eq 'springfield' } keys(%HoH); 

o utilizzando una fetta hash:

delete @HoH{ grep { $HoH{$_}{town} eq 'springfield' } keys(%HoH) }; 
+1

Nelle stringhe 'grep' si sta trattando ('keys% HoH') come hashrefs. – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot, corretto. – ikegami

+2

Come sempre, più pulito e più elegante della soluzione su cui stavo lavorando. Immagino che tu possa scrivere queste cose nel sonno. – ThisSuitIsBlackNot

4

Se è necessario grep o map tramite hash, è possibile considerare di utilizzare grepp o mapp da List::Pairwise. Il vantaggio è che non è più necessario menzionare la variabile hash originale nel blocco di codice grep/map, rendendolo più "funzionale". Quindi, il problema potrebbe essere risolto in questo modo:

use List::Pairwise qw(grepp); 
%HoH = grepp { $b->{town} eq 'springfield' } %HoH; # $a is the current key, $b is the current value 
0
for my $key (keys %HoH) { 
delete $HoH{$key} if(!$HoH{$key}{town}); 
        (OR) 
delete $HoH{$key} if($HoH{$key}{town} !~ m/springfield/); 
} 

utilizzare uno dei opzione di eliminazione avrete la vostra risposta ...