2011-09-22 27 views
11

Ho un semplice hash definito da qualche parte nel file principaleCome inserire hash in hash in Perl

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

In un altro file che voglio aggiungere più traduzioni. Cioè, voglio fare qualcosa di simile:

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

Naturalmente questo codice non avrebbe funzionato: push non funziona con gli hash. Quindi la mia domanda è: qual è un modo semplice ed elegante per inserire un hash di valori in un hash esistente?

non vorrei ricorrere a

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

dal momento che in Perl si suppone essere in grado di fare le cose senza troppe ripetizioni nel codice ...

risposta

9

È possibile assegnare ad una fetta di hash utilizzando le keys e values funzioni. Finché l'hash non viene modificato tra le chiamate, keys restituirà le chiavi nello stesso ordine in cui values restituisce i valori.

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

Questo aiuta! Posso anche scriverlo come '@translations {keys% $ _} = valori $% _ per {" frase N "=>" blah-blah ", ...};' – Pasha

+1

Questa sintassi non mi è venuta in mente, ma è una scorciatoia intelligente. Il ciclo rende probabilmente un pelo meno efficiente, ma dubito che la differenza sia misurabile. – cjm

+0

beh, è ​​un loop su un singolo elemento. Più un modo conveniente per assegnare l'hash anonimo alla variabile $ _. – Pasha

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

Questo copia l'intero hash sopra? Cioè, supponiamo che '% translations' contenga già diverse migliaia di voci. Vuoi creare un hash temporaneo (" frase N "=> ...," frase M "=> ..., ), e quindi assegnare questo hash temp alle% traduzioni? Se è così allora ci sarà un sovraccarico significativo per l'utilizzo di questo metodo, se non è così semplice! – Pasha

+0

@ user958624: sì, lo fa. Una nuova lista il valore è costruito da queste sottoliste e assegnato a '% translations' –

6

È può assegnare ad una fetta hash:

@translations{@keys} = @values; 

o utilizzando dati da un altro hash:

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

Tuttavia, poiché sto aggiungendo molte nuove chiavi, sarà davvero difficile mantenere traccia della corrispondenza tra le chiavi e i loro valori (la cui traduzione corrisponde a quale frase). – Pasha

+0

@ user958624: è possibile utilizzare le matrici per chiavi e valori (vedi l'aggiornamento) –

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

stesso principio risposta di yi_H, ma dimostrando che si può fare su hash esistenti, non solo durante la creazione di '% translations' – plusplus

2

Hash::Merge è un'altra opzione: https://metacpan.org/module/Hash::Merge

anche - non preoccupatevi troppo di ottimizzazione nella copiatura hash - se diventa un problema, esaminare il problema allora. Prima di tutto prova a scrivere un codice chiaramente leggibile e gestibile. Un hash di diverse migliaia di chiavi con valori stringa non è grande!

ciò che non è stato specificato nella sua interrogazione, è se ci sarà alcuna collisione di chiavi (cioè ci potrebbe mai essere due 'Leggi Frase 1 di dai file ...?

+0

Hash :: Merge è eccessivo se non si dispone di una struttura di dati nidificata o se è necessario un trattamento speciale delle chiavi duplicate. – cjm

+1

Sono d'accordo, è in questo caso, ma utile sapere l'esistenza di, quindi ho pensato di parlarne. – plusplus