2011-09-22 21 views
11

tengo un hash sencilla definido en alguna parte del archivo principalCómo insertar de comprobación aleatoria de hash en Perl

our %translations = (
    "phrase 1" => "translation 1", 
    # ... and so on 
    ); 

En otro archivo que desea agregar un poco más traducciones. Es decir, que quiero hacer algo como esto:

push our %translations, (
    "phrase N" => "blah-blah", 
    # .... 
    "phrase M" => "something", 
    ); 

Por supuesto, este código no funcionaría: push no funciona con los hashes. Entonces mi pregunta es: ¿cuál es una forma simple y elegante de insertar un hash de valores en un hash existente?

No me gustaría que recurrir a

$translations{"phrase N"} = "blah-blah"; 
# .... 
$translations{"phrase M"} = "something"; 

ya que en Perl que se supone que será capaz de hacer las cosas sin demasiada repetición en el código ...

Respuesta

9

Puede asignar a una rebanada cifrado usando el keys y values funciones. Siempre que el hash no se modifique entre las llamadas, keys devolverá las claves en el mismo orden en que values devuelve los valores.

our %translations = (
    "phrase 1" => "translation 1", 
); 

{ # Braces just to restrict scope of %add 
    my %add = (
    "phrase N" => "blah-blah", 
    "phrase M" => "something", 
); 
    @translations{keys %add} = values %add; 
} 

# Or, using your alternate syntax: 
@translations{keys %$_} = values %$_ for { 
    "phrase N" => "blah-blah", 
    "phrase M" => "something", 
}; 
+2

¡Esto ayuda! Incluso puedo escribirlo como '@translations {keys% $ _} = values ​​$% _ for {" phrase N "=>" blah-blah ", ...};' – Pasha

+1

Esa sintaxis no se me ocurrió, pero es un atajo inteligente. El ciclo lo hace probablemente menos eficiente, pero dudo que la diferencia sea medible. – cjm

+0

bueno, es un ciclo sobre un solo elemento. Una forma más conveniente de asignar el hash anónimo a la variable $ _. – Pasha

4
%translations = (
    "phrase N" => "blah-blah", 
    # .... 
    "phrase M" => "something", 
    %translations 
    ); 
+0

hace esto copia completa del hash Esto es, supongamos que '% translations' contiene varios miles de entradas ya. ¿Sería una solución crear un hash temporal (" frase N "=> ...," frase M "=> ..., ), y luego asignar este hash de temperatura a% translations? Si es así, habrá una sobrecarga significativa para usar este método, si no, parece lo suficientemente simple! – Pasha

+0

@ user958624: sí, lo hace. Una nueva lista El valor se construye a partir de estas sublistas y se asigna a '% translations' –

6

Usted puede asignar a una rebanada de hash:

@translations{@keys} = @values; 

o el uso de datos de otro de hash:

@translations{keys %new} = values %new; 
+0

Sin embargo, dado que estoy agregando muchas claves nuevas, será muy difícil mantenerlas. seguimiento de la correspondencia entre las claves y sus valores (qué traducción corresponde a qué frase). – Pasha

+0

@ user958624: puede usar matrices para claves y valores (ver la actualización) –

15
%translations = (%translations, %new_translations); 
+0

mismo principio que la respuesta de yi_H, pero mostrando que puede hacerlo en hashes existentes, no solo al crear '% translations' – plusplus

2

Hash::Merge es otra opción: https://metacpan.org/module/Hash::Merge

también - no se preocupe demasiado acerca de la optimización de la copia hashes - si se convierte en un problema, a continuación, buscar en ella. Simplemente intente escribir un buen código legible y fácil de mantener antes que nada. ¡Un hash de varios miles de claves con valores de cadena no es grande!

lo que no se ha especificado en su pregunta, es si habrá una colisión de claves (es decir, podría haber alguna vez dos 'Frase del 1 de lectura de los archivos ...?

+0

Hash :: Merge es exagerado a menos que tenga una estructura de datos anidada o necesite un tratamiento especial de claves duplicadas. – cjm

+1

estoy de acuerdo, es en este caso, pero útil para saber la existencia de, así que pensé en mencionarlo. – plusplus

Cuestiones relacionadas