Comment puis-je imprimer le contenu d'un hachage en Perl?

167

Je continue à imprimer mon hachage en tant que # de buckets / # alloué. Comment imprimer le contenu de mon hachage?

Sans utiliser une whileboucle serait le plus préférable (par exemple, une seule ligne serait le meilleur).

Kys
la source

Réponses:

253

Data :: Dumper est votre ami.

use Data::Dumper;
my %hash = ('abc' => 123, 'def' => [4,5,6]);
print Dumper(\%hash);

sortira

$VAR1 = {
          'def' => [
                     4,
                     5,
                     6
                   ],
          'abc' => 123
        };
tétromino
la source
3
l'affiche originale pourrait également vouloir examiner les différentes options Data :: Dumper, en particulier l'activation de 'Sortkeys' peut être très utile
plusplus
1
@JonathanDay Il me manquait ce détail et c'était utile! Merci!
Sos
5
Que signifie ajouter une barre oblique devant le%?
shampooing du
16
L'opérateur slash @shampoo crée une référence, un peu comme l' &opérateur en C et C ++. La raison pour laquelle cela compte dans ce contexte est qu'en Perl, si vous appelez une fonction avec une valeur de hachage comme argument, cette valeur de hachage est listée et étendue en plusieurs arguments - ce %hsh=("a" => 1, "b" => 2); foo(%hsh);serait donc équivalent à foo("a", 1, "b", 2). Si vous souhaitez à la place que la fonction opère sur le hachage lui-même, vous devez passer une référence au hachage: foo(\%hsh);Voir perldoc.perl.org/perlsub.html#Pass-by-Reference
tetromino
63

Facile:

print "$_ $h{$_}\n" for (keys %h);

Élégant, mais en fait 30% plus lent (!):

while (my ($k,$v)=each %h){print "$k $v\n"}
Jonathan Graehl
la source
9
Sleazy: imprime "@_ \ n" while @_ = each% h
FMc
Je pense que vous voulez dire print "$_ $h{$_}\n" for (keys %h);, $kn'existe pas dans cet exemple.
Chas. Owens
4
Également, comparez-vous avant de faire des déclarations sur l'efficacité (ou du moins qualifiez le type d'efficacité dont vous parlez). La forboucle est plus rapide que les whilejusqu'à au moins 10 000 clés: gist.github.com/151792
Chas. Owens
1
Bien sûr, vous avez raison re: $ k. Mais c'est plus efficace en Perl 6! :) Oui, vous avez raison aussi. Je n'aurais jamais pensé à optimiser ou profiler mon Perl, mais je suis heureux d'apprendre cela. Bien sûr, chacun devrait être plus efficace (car il n'y a pas de recherche de hachage supplémentaire sur la clé). Mais c'est ~ 30% plus lent!
Jonathan Graehl
Salut, Jonathan Graehl. Désolé, je ne comprends toujours pas. Vous dites que chacun est environ 30% plus lent en fonction de quoi? Est-ce que chaque fois, pour chaque situation, un écart de 30%?
Carlos Sá
24

À des fins de débogage, j'utiliserai souvent YAML.

use strict;
use warnings;

use YAML;

my %variable = ('abc' => 123, 'def' => [4,5,6]);

print "# %variable\n", Dump \%variable;

Résulte en:

# %variable
---
abc: 123
def:
  - 4
  - 5
  - 6

D'autres fois, j'utiliserai Data::Dump. Vous n'avez pas besoin de définir autant de variables pour le faire sortir dans un bon format que vous le faites pour Data::Dumper.

use Data::Dump = 'dump';

print dump(\%variable), "\n";
{ abc => 123, def => [4, 5, 6] }

Plus récemment, j'ai utilisé Data::Printerpour le débogage.

use Data::Printer;
p %variable;
{
    abc   123,
    def   [
        [0] 4,
        [1] 5,
        [2] 6
    ]
}

(Le résultat peut être beaucoup plus coloré sur un terminal)

Contrairement aux autres exemples que j'ai montrés ici, celui-ci est conçu explicitement pour être uniquement à des fins d'affichage. Ce qui apparaît plus facilement si vous videz la structure d'une variable liée ou celle d'un objet.

use strict;
use warnings;

use MTie::Hash;
use Data::Printer;

my $h = tie my %h, "Tie::StdHash";
@h{'a'..'d'}='A'..'D';
p %h;
print "\n";
p $h;
{
    a   "A",
    b   "B",
    c   "C",
    d   "D"
} (tied to Tie::StdHash)

Tie::StdHash  {
    public methods (9) : CLEAR, DELETE, EXISTS, FETCH, FIRSTKEY, NEXTKEY, SCALAR, STORE, TIEHASH
    private methods (0)
    internals: {
        a   "A",
        b   "B",
        c   "C",
        d   "D"
    }
}
Brad Gilbert
la source
avoir les couleurs est "soigné", mais soit je fais quelque chose de mal, soit en utilisant "use Data :: Printer; p% var;" n'imprime pas les flèches dans les hachages, et pour un débutant comme moi qui aide
Sos
@Sosi Si vous regardez la sortie dans la réponse, vous verrez qu'elle ne produit pas ce =>que vous attendez. Il imprime à la place toujours la clé, plusieurs espaces, puis la valeur. Ce qui aide un humain à analyser la sortie.
Brad Gilbert
12

La réponse dépend de ce que contient votre hachage. Si vous avez un simple hachage, un simple

print map { "$_ $h{$_}\n" } keys %h;

ou

print "$_ $h{$_}\n" for keys %h;

fera l'affaire, mais si vous avez un hachage rempli de références, vous obtiendrez quelque chose qui peut parcourir ces références et produire une sortie sensible. Cette marche des références est normalement appelée sérialisation. Il existe de nombreux modules qui implémentent différents styles, certains des plus populaires sont:

Etant donné que cela Data::Dumperfait partie de la bibliothèque principale de Perl, c'est probablement la plus populaire; cependant, certains des autres modules ont de très bonnes choses à offrir.

Chas. Owens
la source
10

Mon préféré: Smart :: Commentaires

use Smart::Comments;
# ...

### %hash

C'est tout.

Axeman
la source
5
Désolé, votez contre moi pour des trucs qui détournent les commentaires pour des fonctionnalités réelles. Un programmeur de maintenance pourrait passer toute la journée à essayer de comprendre pourquoi un code comme celui-ci imprimait des choses inattendues.
MikeKulls
2
@MikeKulls, np. C'est un filtre source, donc je comprends. De plus, ayant écrit des scripts qui vérifient que chaque module que j'ai mis en préparation de la production ne le fait pas use Smart::Comments, je le vois aussi de ce point de vue. Mais au comptoir, Smart::Commentsest assez bien comportée comme un scope module, il ne devrait pas être un comportement de sortie dans un module qui ne aussi utiliser SC. Ainsi, le problème serait isolé de ces portées avec une instruction use . Si vous dites qu'un programmeur de maintenance n'a aucune responsabilité de lire la documentation sur les modules inclus, je ne peux pas être d'accord. Encore, merci pour vos commentaires
Axeman
7
Je ne dis pas qu'ils n'ont pas de responsabilité, mais ce n'est probablement pas la première chose qu'ils recherchent. N'ayant jamais vu le module Smart Comments auparavant, je ne saurais pas pourquoi le code ci-dessus imprimait quelque chose. Je pourrais passer des jours à sauter le commentaire sans même le traiter parce que les commentaires ne devraient rien faire. Leur faire faire quelque chose est très mauvais imo. Ils peuvent être utilisés pour générer de la documentation, etc. tant qu'ils ne modifient pas le comportement du programme.
MikeKulls
4

Boucle:

foreach(keys %my_hash) { print "$_ / $my_hash{$_}\n"; }

Fonctionnel

map {print "$_ / $my_hash{$_}\n"; } keys %my_hash;

Mais pour l'élégance pure, je devrais choisir celui de wrang-wrang. Pour mon propre code, je choisirais mon foreach. Ou l'utilisation du Dumper de Tetro.

Paul Nathan
la source
3
Il n'y a pas de différence fonctionnelle entre vos utilisations de foreachet map. mapdevrait être utilisé pour les transformations de liste, pas dans un contexte vide pour émuler une boucle
for
il serait intéressant de voir les résultats 'byte code' de chacun ... Je me demande si la carte est plus ou moins efficace.
Ape-inago
2

Le moyen le plus simple dans mes expériences est d'utiliser simplement Dumpvalue .

use Dumpvalue;
...
my %hash = { key => "value", foo => "bar" };
my $dumper = new DumpValue();
$dumper->dumpValue(\%hash);

Fonctionne comme un charme et vous n'avez pas à vous soucier du formatage du hachage, car il le produit comme le débogueur Perl (idéal pour le débogage). De plus, Dumpvalue est inclus avec l'ensemble de modules Perl, vous n'avez donc pas à vous soucier du CPAN si vous êtes derrière une sorte de proxy draconien (comme je suis au travail).

Weegee
la source
1

Si vous voulez être pédant et vous en tenir à une seule ligne (sans instructions d'utilisation ni shebang), alors je vais en quelque sorte reprendre la réponse de tétromino et suggérer:

print Dumper( { 'abc' => 123, 'def' => [4,5,6] } );

Ne rien faire de spécial autre que d'utiliser le hachage anonyme pour ignorer la variable temporaire;)

Kyle Walsh
la source
L'OP dit qu'il a "mon hachage" qui doit être imprimé. Cette réponse est juste de l'intelligence pour elle-même
juste le
OP espérait le faire en une seule ligne. Je montrais juste une façon de le faire en une seule ligne. Cela mérite donc un vote défavorable?
Kyle Walsh
1

J'ajoute un espace pour chaque élément du hachage pour bien le voir:

print map {$_ . " "} %h, "\n";
carlos_lm
la source
1

J'aime vraiment trier les clés dans un code de doublure:

print "$_ => $my_hash{$_}\n" for (sort keys %my_hash);
labiste
la source