hashes perl hash

hashes - ¿Cómo puedo obtener una única parte de un hash en Perl?



hash of hashes perl (7)

¿Hay una manera de obtener un sub-hash? ¿Necesito usar una porción de hash?

Por ejemplo:

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

Solo quiero

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


Demasiada programación funcional me lleva a pensar primero en zip .

Con la List::MoreUtils instalado,

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

Desafortunadamente, el prototipo de List :: MoreUtils''s zip inhibits.

zip @keys, @hash{@keys};

Si realmente quieres evitar la variable intermedia, podrías

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

O simplemente escribe tu propio zip sin el prototipo problemático. (Esto no necesita List :: MoreUtils en absoluto.)

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

Si vas a estar mutando en el lugar,

%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;

evita la copia adicional en la que incurren las soluciones de map y zip . (Sí, mutar el hash mientras está iterando es seguro ... siempre y cuando la mutación solo elimine el par iterado más reciente).


FWIW, yo uso Moose :: Autobox aquí:

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

En la vida real, uso esto para extraer "username" y "password" de un envío de formulario, y se lo paso a $c->authenticate Catalyst (que espera, en mi caso, un hashref que contiene el nombre de usuario y la contraseña, pero nada más) ).


Lo nuevo en Perl 5.20 son los cortes de hash que devuelven las claves y los valores utilizando% como en la última línea aquí:

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!


Otra forma más:

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


Probablemente quieras ensamblar una lista de claves que deseas:

my @keys = qw(a b);

Y luego usa un bucle para hacer el hash:

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

O:

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

(Mi preferencia es la segunda, pero la que más te guste es la mejor).


Un hash es un contenedor desordenado, pero el término segmento solo tiene sentido en términos de un contenedor ordenado. Tal vez mirar en el uso de una matriz. De lo contrario, es posible que solo tenga que eliminar todos los elementos que no desea que produzcan su ''sub-hash''.


Los cortes de hash devuelven los valores asociados con una lista de claves. Para obtener una porción de hash, cambia el sigilo a @ y proporciona una lista de claves (en este caso "a" y "b" ):

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

A menudo, puede utilizar un operador de palabra cita para producir la lista:

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

También puede asignar una porción de hash, por lo que si desea un hash nuevo que contenga un subconjunto de otro hash, puede decir

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

Muchas personas usarán un map lugar de cortes de hash:

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

A partir de Perl 5.20.0, puede obtener las claves y los valores en un solo paso si usa el% sigil en lugar del @ sigil:

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