2009-06-11 10 views
17

Czy istnieje sposób, aby uzyskać sub-hash? Czy muszę użyć skrótu mieszającego?Jak mogę uzyskać tylko część wartości skrótu w Perlu?

Na przykład:

%hash = (a => 1, b => 2, c => 3); 

Chcę tylko

%hash = (a => 1, b => 2); 
+0

Ponieważ nie ma nic logicznie "plaster" na podejrzewam, że coś ma wspólnego z "mapą". W tablicy można to zrobić na podstawie indeksu, ale w hasz nie ma wiarygodnej wewnętrznej reprezentacji danych w nim. Potrzebujesz pewnego rodzaju kwalifikatora (regex?), Aby zdefiniować, co powinno przejść do subhash, a co nie. –

+3

BTW, twoja składnia hash jest nieprawidłowa: użyj nawiasów okrągłych "()" dla zwykłego skrótu, "{}" dla anonimowych odwołań hash. – trendels

Odpowiedz

46

Hash slices zwraca wartości związane z listą kluczy. Aby dostać kawałek skrótu umożliwiającego zmianę sigil do @ i dostarczyć listę kluczy (w tym przypadku "a" i "b"):

my @items = @hash{"a", "b"}; 

Często można użyć operatora cytat słowo produkować listę:

my @items = @hash{qw/a b/}; 

można również przypisać do plasterka hash, więc jeśli chcesz nowy skrót, który zawiera podzbiór innego hash można powiedzieć

my %new_hash; 
@new_hash{qw/a b/} = @hash{qw/a b/}; 

Wiele osób będzie korzystać z map zamiast kromki hash:

my %new_hash = map { $_ => $hash{$_} } qw/a b/; 

Począwszy Perl 5.20.0, można dostać klucze i wartości w jednym etapie w przypadku korzystania z% sigil zamiast @ Sigil:

my %new_hash = %hash{qw/a b/}; 
+0

to sprawia, że ​​dlaczego "map" działa w/hashe trochę jaśniej dla mnie. Dzięki –

+0

Larry Wall, brian d foy i ... Chas. Owens ... dziękuję za tak wyczerpujące wyjaśnienie! – bernie

+4

Powinieneś prawdopodobnie uczynić go bardziej zrozumiałym, że segment mieszający ma tylko wartości, a nie pary klucz/wartość. – ysth

-3

Hash jest nieuporządkowana pojemnik, ale kawałek termin tylko naprawdę ma sens pod względem uporządkowanej pojemniku. Może zajrzyj do tablicy. W przeciwnym razie możesz po prostu usunąć wszystkie elementy, których nie chcesz tworzyć "sub-hash".

+0

W języku Perl plasterki skrótu są użyteczne i w pełni obsługiwane. Aby dowiedzieć się więcej przeczytaj ponownie [sekcja "Plasterki" w _perldata_] (http://perldoc.perl.org/perldata.html#Slices). –

9

Można by pewnie chcą zebrać listę kluczy chcesz:

my @keys = qw(a b); 

a następnie użyć pętli, aby hash:

my %hash_slice; 
for(@keys) { 
    $hash_slice{$_} = %hash{$_}; 
} 

czyli

my %hash_slice = map { $_ => $hash{$_} } @keys; 

(Moja preferencja to druga, ale ta, która Ci się podoba jest najlepsza.)

3

Zbyt wiele programowania funkcjonalnego prowadzi mnie najpierw do myślenia o numerze zip.

Z List::MoreUtils zainstalowanego

use List::MoreUtils qw(zip); 

%hash = qw(a 1 b 2 c 3); 
@keys = qw(a b); 
@values = @hash{@keys}; 
%hash = zip @keys, @values; 

Niestety prototyp Lista :: MoreUtils na zip hamuje

zip @keys, @hash{@keys}; 

Jeśli naprawdę chcesz, aby uniknąć zmienną pośrednią, można

zip @keys, @{[@hash{@keys}]}; 

Lub po prostu napisz własną zip bez problematycznego prototypu. (To nie potrzebuje List :: MoreUtils w ogóle.)

sub zip { 
    my $max = -1; 
    $max < $#$_and $max = $#$_ for @_; 
    map { my $ix = $_; map $_->[$ix], @_; } 0..$max; 
} 

%hash = zip \@keys, [@hash{@keys}]; 

Jeśli masz zamiar być mutacji w miejscu,

%hash = qw(a 1 b 2 c 3); 
%keep = map +($_ => 1), qw(a b); 
$keep{$a} or delete $hash{$a} while ($a, $b) = each %hash; 

unika dodatkowego kopiowania że rozwiązania map i zip ponieść. (. Tak, mutowania hash gdy jesteś iteracji nad nim jest bezpieczny ... tak długo, jak mutacja jest usuwanie tylko ostatnio iterowany parę)

+0

Wyjaśnij to, proszę - '% keep = map + ($ _ => 1), qw (a b);'? –

3

FWIW używam Moose :: Autobox tutaj:

my $hash = { a => 1, b => 2, c => 3, d => 4 }; 
$hash->hslice([qw/a b/]) # { a => 1, b => 2 }; 

W prawdziwym życiu używam tego, aby wyodrębnić "nazwę użytkownika" i "hasło" z przesłanego formularza, i przekazać to do Catalyst $c->authenticate (który oczekuje, w moim przypadku, hashref zawierający nazwę użytkownika i hasło, ale nic więcej).

+1

Co to jest $ hash-> hslice (qw/a b /) lepsze niż @ {$ hash} {qw/a b /}? Czy jest to jeden z tych przypadków, w których, jeśli muszę prosić, jestem zbyt daleko, by to zrozumieć? –

+4

Powinieneś mieć szablon odpowiedzi, aby "Używam łosia ::" było na początku każdej odpowiedzi. :) –

+1

Chas. Owens: nie to robi hslice. @ {$ hash} {...} zwraca listę wartości; hslice zwraca nowe odwołanie do skrótu za pomocą obu kluczy i wartości. – jrockway

6

Jeszcze innym sposobem:

my @keys = qw(a b); 
my %hash = (a => 1, b => 2, c => 3); 
my %hash_copy; 
@hash_copy{@keys} = @hash{@keys}; 
2

Nowy Perl 5.20 jest plastry cebulą powracający klucze, jak również wartości za pomocą% jak w ostatnim wierszu tutaj:

my %population = ('Norway',5000000,'Sweden',9600000,'Denmark',5500000); 
my @slice_values = @population{'Norway','Sweden'}; # all perls can do this 
my %slice_hash = %population{'Norway','Sweden'}; # perl >= 5.20 can do this! 
Powiązane problemy