2011-09-22 4 views
11

J'ai un hachage simple, défini quelque part dans le fichier principalComment insérer hachage dans hachage en Perl

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

Dans un autre dossier que je veux ajouter quelques traductions. À savoir, je veux faire quelque chose comme ceci:

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

Bien sûr ce code ne fonctionnerait pas: push ne fonctionne pas avec hash. Donc ma question est: qu'est-ce qu'un moyen simple et élégant d'insérer un hachage de valeurs dans un hachage existant?

Je ne voudrais pas avoir recours à

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

depuis Perl vous êtes censé être en mesure de faire des choses sans trop de répétitions dans votre code ...

Répondre

9

Vous pouvez attribuer à une tranche de hachage en utilisant les fonctions keys et values. Tant que le hachage n'est pas modifié entre les appels, keys renverra les clés dans le même ordre que values renvoie les valeurs.

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

Cela aide! Je peux même l'écrire comme '@translations {keys% $ _} = values ​​$% _ pour {" phrase N "=>" blah-blah ", ...};' – Pasha

+1

Cette syntaxe ne m'est pas venue à l'esprit, mais c'est un raccourci intelligent. La boucle rend probablement un poil moins efficace, mais je doute que la différence soit mesurable. – cjm

+0

Eh bien, c'est une boucle sur un seul élément. Plus d'un moyen pratique d'attribuer le hachage anonyme à la variable $ _. – Pasha

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

Est-ce que cette copie l'ensemble de hachage Supposons que «% translations» contienne déjà plusieurs milliers d'entrées. Voulez-vous créer un hachage temporaire («phrase N» => ..., «phrase M» => ..., ), puis assigner ce hachage temp aux% translations? Si oui, il y aura un surcoût important pour l'utilisation de cette méthode, sinon il semble assez simple! – Pasha

+0

@ user958624: oui, c'est le cas. La valeur est construite à partir de ces sous-listes et est affectée au '% translations' –

6

Vous peut assigner à une tranche de hachage:

@translations{@keys} = @values; 

ou en utilisant des données provenant d'un autre hachage:

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

Cependant, puisque j'ajoute beaucoup de nouvelles clés, ce sera vraiment difficile à garder suivi de la correspondance entre les clés et leurs valeurs (quelle traduction correspond à quelle phrase). – Pasha

+0

@ user958624: vous pouvez utiliser des tableaux pour les clés et les valeurs (voir la mise à jour) –

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

même principe que la réponse de yi_H, mais montrant que vous pouvez le faire sur des hachages existants, pas seulement en créant '% translations' – plusplus

2

Hash::Merge est une autre option: https://metacpan.org/module/Hash::Merge

aussi - ne vous inquiétez pas trop sur l'optimisation de la copie hachages - si elle devient un problème, se pencher alors. Essayez simplement d'écrire du bon code clair et lisible, tout d'abord. Un hachage de plusieurs milliers de clés avec des valeurs de chaîne n'est pas important!

ce que vous n'avez pas spécifié dans votre question est de savoir s'il y aura une collision de clés (c.-à-pourrait-il y avoir deux « lecture des fichiers de phrase 1 ...?

+0

Hash :: Merge est surchargé sauf si vous avez une structure de données imbriquée ou si vous avez besoin d'un traitement spécial des clés en double. – cjm

+1

je suis d'accord, il est dans ce cas, mais utile de connaître l'existence de, alors pensé que je voudrais juste le mentionner. – plusplus

Questions connexes