Come posso stampare il contenuto di un hash in Perl?


167

Continuo a stampare il mio hash come # di bucket / # allocato. Come faccio a stampare il contenuto del mio hash?

Senza usare un whileloop sarebbe preferibile (ad esempio, sarebbe meglio un one-liner ).

Risposte:


253

Data :: Dumper è tuo amico.

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

uscirà

$VAR1 = {
          'def' => [
                     4,
                     5,
                     6
                   ],
          'abc' => 123
        };

3
il poster originale potrebbe anche voler esaminare le varie opzioni Data :: Dumper, in particolare l'attivazione di 'Sortkeys' può essere molto utile
plusplus

1
@JonathanDay Mi mancavano quei dettagli ed è stato utile! Grazie!
Sos,

5
Che cosa significa aggiungere una barra davanti alla%?
shampoo

16
L'operatore slash di @shampoo crea un riferimento, un po 'come l' &operatore in C e C ++. La ragione per cui è importante in questo contesto è che in Perl, se si chiama una funzione con un valore hash come argomento, quel valore hash viene elencato ed espanso in più argomenti - quindi %hsh=("a" => 1, "b" => 2); foo(%hsh);sarebbe equivalente a foo("a", 1, "b", 2). Se invece desidera che la funzione di operare sul hash per sé, è necessario passare un riferimento alla hash: foo(\%hsh);See perldoc.perl.org/perlsub.html#Pass-by-Reference
tetromino

63

Facile:

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

Elegante, ma in realtà più lento del 30% (!):

while (my ($k,$v)=each %h){print "$k $v\n"}

9
Sleazy: stampa "@_ \ n" mentre @_ = ogni% h
FMc

Penso che intendi print "$_ $h{$_}\n" for (keys %h);, $knon esiste in questo esempio.
Chas. Owens,

4
Inoltre, fai un benchmark prima di fare affermazioni sull'efficienza (o almeno qualifica il tipo di efficienza di cui stai parlando). Il forciclo è più veloce di whilealmeno 10.000 tasti: gist.github.com/151792
Chas. Owens,

1
Ovviamente hai ragione riguardo a $ k. Ma è più efficiente in Perl 6! :) Sì, anche tu hai ragione. Non avrei mai pensato di ottimizzare o profilare il mio Perl, ma sono felice di saperlo. Ovviamente, ognuno dovrebbe essere più efficiente (perché non esiste una ricerca hash aggiuntiva sulla chiave). Ma è ~ 30% più lento!
Jonathan Graehl,

Ciao Jonathan Graehl. Scusa, ancora non capisco. Stai dicendo che ognuno è ~ 30% più lento in base a cosa? Ogni volta, per ogni situazione, è un divario del 30%?
Carlos Sá,


24

Per scopi di debug userò spesso YAML.

use strict;
use warnings;

use YAML;

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

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

Risultati in:

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

Altre volte userò Data::Dump. Non è necessario impostare quante più variabili per ottenere l'output in un formato piacevole di quello che si fa Data::Dumper.

use Data::Dump = 'dump';

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

Più recentemente ho usato Data::Printerper il debug.

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

(Il risultato può essere molto più colorato su un terminale)

A differenza degli altri esempi che ho mostrato qui, questo è progettato esplicitamente per essere solo a scopo di visualizzazione. Che si presenta più facilmente se scarichi la struttura di una variabile legata o quella di un oggetto.

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"
    }
}

avere i colori è "pulito", ma o sto facendo qualcosa di sbagliato, o usando "usa Data :: Stampante; p% var;" non stampa le frecce negli hash e per un principiante come me che aiuta
Sos

@Sosi Se guardi l'output nella risposta, vedrai che non produce l'output =>che ti aspetti. Invece stampa sempre la chiave, diversi spazi e quindi il valore. Ciò aiuta una scansione umana sull'output.
Brad Gilbert,

12

La risposta dipende da cosa c'è nel tuo hash. Se hai un hash semplice, un semplice

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

o

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

lo farà, ma se hai un hash che è popolato di riferimenti, avrai qualcosa che può camminare su quei riferimenti e produrre un risultato sensato. Questa camminata dei riferimenti è normalmente chiamata serializzazione. Esistono molti moduli che implementano stili diversi, alcuni dei più popolari sono:

A causa del fatto che Data::Dumperfa parte della libreria Perl di base, è probabilmente la più popolare; tuttavia, alcuni degli altri moduli hanno cose molto buone da offrire.


10

Il mio preferito: Smart :: Commenti

use Smart::Comments;
# ...

### %hash

Questo è tutto.


5
Mi dispiace, vota verso il basso da parte mia per cose che dirottano i commenti per la funzionalità effettiva. Un programmatore di manutenzione potrebbe passare tutto il giorno a cercare di capire perché un codice del genere stia stampando cose inaspettate.
MikeKulls,

2
@MikeKulls, np. È un filtro sorgente, quindi ho capito. Inoltre, avendo scritto degli script che controllano ogni modulo che ho messo nella preparazione di produzione che non lo fa use Smart::Comments, lo vedo anche da quella prospettiva. Ma per il contatore, Smart::Commentssi comporta abbastanza bene come un modulo con ambito , non dovrebbe esserci un comportamento di output in nessun modulo che non usi anche SC. Quindi, il problema sarebbe isolato a quegli ambiti con un'istruzione use . Se stai dicendo che un programmatore di manutenzione non ha alcuna responsabilità di leggere il documento sui moduli inclusi, non posso essere d'accordo. Comunque, grazie per il commento
Axeman

7
Non sto dicendo che non hanno una responsabilità, ma non è probabile che sia la prima cosa che cercano. Non avevo mai visto il modulo Smart Comments prima di non sapere perché il codice sopra stava stampando qualcosa. Potrei passare giorni a saltare il commento e nemmeno a elaborarlo perché i commenti non dovrebbero fare nulla. Far loro fare qualcosa è molto male imo. Possono essere utilizzati per generare documentazione ecc. Purché non alterino il comportamento del programma.
MikeKulls

4

looping:

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

Funzionale

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

Ma per pura eleganza, dovrei scegliere quello di Wrang Wrang. Per il mio codice, sceglierei la mia foreach. O l'uso di Detro di Tetro.


3
Non c'è alcuna differenza funzionale tra i tuoi usi di foreache map. mapdovrebbe essere usato per le trasformazioni dell'elenco, non in un contesto vuoto per emulare un for-loop
friedo

sarebbe interessante vedere i risultati del 'codice byte' di ciascuno ... Mi chiedo se la mappa sia più o meno efficiente.
Ape-inago,

2

Il modo più semplice nelle mie esperienze è usare solo Dumpvalue .

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

Funziona come un incantesimo e non devi preoccuparti di formattare l'hash, in quanto lo emette come fa il debugger Perl (ottimo per il debug). Inoltre, Dumpvalue è incluso nel set di moduli Perl, quindi non devi fare confusione con CPAN se sei dietro un qualche tipo di proxy draconiano (come se fossi al lavoro).


1

Se vuoi essere pedante e mantenerlo su una riga (senza dichiarazioni d'uso e shebang), allora mi sposterò un po 'sulla risposta del tetromino e suggerirò:

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

Non fare nulla di speciale oltre all'utilizzo dell'hash anonimo per saltare la variabile temp;)


L'OP afferma che ha "il mio hash" che deve essere stampato. Questa risposta è solo intelligenza per se stessa
justintime

OP sperava di farlo in una riga. Stavo solo mostrando un modo di fare una riga. Quindi è degno di un voto negativo?
Kyle Walsh,

1

Aggiungo uno spazio per ogni elemento dell'hash per vederlo bene:

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

1

Mi piace molto ordinare le chiavi in ​​un codice di copertina:

print "$_ => $my_hash{$_}\n" for (sort keys %my_hash);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.