2017-03-15 2 views
0

Je construis une petite bibliothèque qui transforme les données de journal en un fichier de type CSV qui peut être importé par un tableur. Pour la sortie, je suis intéressé par une option pour afficher des légendes conviviales pour les colonnes de la table si nécessaire. Cela devrait être une option pour que l'outil puisse également être utilisé avec un minimum d'effort. Je suis venu avec un tableau pour la spécification de colonne qui contient des scalaires simples pour les clés ou des références de hachage avec une paire de clé et de valeur. J'y accède via des clés et des valeurs qui me paraissent un peu étranges.accéder aux références de "paire de hachage" utilisées pour la spécification de colonne

Existe-t-il un moyen plus simple d'accéder à la clé et à la valeur d'un hachage contenant uniquement une paire?

(j'ai essayé de simplifier le code autant que possible.)

#!/usr/bin/perl -w 
use strict; 
use warnings; 

# some sample data 
my @rows = (
    {x => 1, y => 2}, 
    {y => 5, z => 6}, 
    {x => 7, z => 9}, 
); 

sub print_table { 
    my @columns = @_; # columns of interest with optional header replacement 
    my @keys; # for accessing the data values 
    my @captions; # for display on column headers 
    for (@columns) { 
     if (ref($_) eq 'HASH') { 
      push @keys, keys %$_; 
      push @captions, values %$_; 
     } else { 
      push @keys, $_; 
      push @captions, $_; 
     } 
    } 
    print join ("\t", @captions), "\n"; 
    for my $row (@rows) { 
     print join ("\t", (map {$row->{$_} // ''} @keys)), "\n"; 
    } 
} 

print_table({x=>'u'}, 'y'); 
+0

Quel est le problème avec '' keys' et values'? Votre code est déjà assez simple. – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot ... c'est ce que je pensais, mais parce que [push] (http://perldoc.perl.org/functions/push.html) ouvre un contexte de liste, j'ai trouvé cela ** trompeur ** en raison de l'intention caractère singleton des arguments. – Wolf

+0

Rien de trompeur à ce sujet, vous pouvez «pousser» des scalaires simples aussi bien que des scalaires multiples: 'push @foo, $ bar'. Je pense que vous pensez trop. – ThisSuitIsBlackNot

Répondre

2

Tout ce que vous devez:

my ($k, $v) = %hash; 

Alors

my ($k, $v) = %$_; 
push @keys,  $k; 
push @captions, $v; 

ou

push @keys,  (%$_)[0]; 
push @captions, (%$_)[1]; 
+0

Bien que vous apportiez cette version ('my ($ k, $ v) =% hash;'). Entre-temps, j'ai compris cela moi-même. Et ça avait l'air si simple. Cela nous enseigne aussi une leçon sur les listes. – Wolf

+0

BTW: considérez-vous que ces "hachages par paire" sont normaux ou indiquent-ils généralement de mauvaises solutions? ... et pouvez-vous suggérer une solution plus idiomatique pour ce type de remplacement? – Wolf

+1

C'est inhabituel, mais pas nécessairement mauvais. Un tableau (par exemple '[x => 'u']') serait plus pratique ('push @keys, $ _-> [0];'). Est-ce vraiment si grave si l'appelant devait faire 'print_table (x => 'u', y => 'y')'? – ikegami

0

Utilisez each.

De perldoc:

Lorsqu'elle est appelée hachage dans un contexte de liste, retourne une liste 2 éléments composé de la clé et la valeur de l'élément suivant d'un hachage.

Mais ne pas oublier de réinitialiser l'itérateur à l'aide keys(%hash)each sera par la suite ou après échec.

my ($k, $v) = each(%$_); 
keys(%$_); 
+0

Lit bien. Est-il "normal" d'utiliser 'each' en dehors des boucles? – Wolf

+2

@Wolf, Non. Mise en garde ajoutée pour répondre. – ikegami