Como posso imprimir o conteúdo de um hash no Perl?


167

Continuo imprimindo meu hash como # de baldes / # alocados. Como imprimo o conteúdo do meu hash?

Sem o uso de um whileloop seria o mais preferível (por exemplo, um one-liner seria o melhor).

Respostas:


253

Data :: Dumper é seu amigo.

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

irá produzir

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

3
o cartaz original também pode querer olhar para as várias opções Data :: Dumper, em particular de viragem na 'SORTKEYS' pode ser muito útil
plusplus

1
@ JonathanDay Estava faltando esse detalhe e foi útil! Obrigado!
Sos

5
O que significa adicionar uma barra na frente do%?
Shampoo

16
O operador @shampoo slash cria uma referência, um pouco como o &operador em C e C ++. A razão pela qual isso importa nesse contexto é que, em Perl, se você chamar uma função com um valor de hash como argumento, esse valor de hash será listado e expandido em vários argumentos - portanto, %hsh=("a" => 1, "b" => 2); foo(%hsh);seria equivalente a foo("a", 1, "b", 2). Se você em vez disso quer a função de operar no próprio haxixe, você precisa passar uma referência para o hash: foo(\%hsh);Veja perldoc.perl.org/perlsub.html#Pass-by-Reference
tetromino

63

Fácil:

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

Elegante, mas na verdade 30% mais lento (!):

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

9
Sleazy: print "@_ \ n", enquanto @_ = cada% h
FMc

Eu acho que você quer dizer print "$_ $h{$_}\n" for (keys %h);, $knão existe nesse exemplo.
Chas. Owens

4
Além disso, faça um benchmark antes de fazer reivindicações sobre eficiência (ou pelo menos qualificar o tipo de eficiência que você está falando). O forloop é mais rápido que as whileaté 10.000 chaves: gist.github.com/151792
Chas. Owens

1
Claro que você está certo: $ k. Mas é mais eficiente no Perl 6! :) Sim, você também está certo. Eu nunca teria pensado em otimizar ou criar um perfil no meu Perl, mas fico feliz em aprender isso. Obviamente, cada um deve ser mais eficiente (porque não há pesquisa de hash extra na chave). Mas é ~ 30% mais lento!
11138 Jonathan Graehl

Olá, Jonathan Graehl. Desculpe, ainda não entendi. Você está dizendo que cada um é ~ 30% mais lento com base no quê? É sempre, para todas as situações, uma diferença de 30%?
Carlos Sá


24

Para fins de depuração, usarei frequentemente YAML.

use strict;
use warnings;

use YAML;

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

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

Resulta em:

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

Outras vezes eu usarei Data::Dump. Você não precisa definir tantas variáveis ​​para que ele a produza em um formato agradável do que o necessário Data::Dumper.

use Data::Dump = 'dump';

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

Mais recentemente, tenho usado Data::Printerpara depuração.

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

(O resultado pode ser muito mais colorido em um terminal)

Ao contrário dos outros exemplos que mostrei aqui, este foi projetado explicitamente para ser apenas para fins de exibição. O que aparece mais facilmente se você despejar a estrutura de uma variável vinculada ou a de um objeto.

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

ter as cores é "legal", mas estou fazendo algo errado ou usando "use Data :: Printer; p% var;" não imprime as setas em hashes, e para um novato como eu que ajuda
Sos

@Sosi Se você olhar para a saída na resposta, verá que ela não sai da maneira =>esperada. Em vez disso, sempre imprime a chave, vários espaços e, em seguida, o valor. O que ajuda uma varredura humana sobre a saída.
Brad Gilbert

12

A resposta depende do que está no seu hash. Se você tem um hash simples, um simples

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

ou

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

funcionará, mas se você tiver um hash preenchido com referências, terá algo que poderá percorrer essas referências e produzir uma saída sensata. Essa caminhada das referências é normalmente chamada de serialização. Existem muitos módulos que implementam estilos diferentes, alguns dos mais populares são:

Devido ao fato de fazer Data::Dumperparte da biblioteca principal do Perl, é provavelmente o mais popular; no entanto, alguns dos outros módulos têm coisas muito boas a oferecer.


10

Meu favorito: Smart :: Comentários

use Smart::Comments;
# ...

### %hash

É isso aí.


5
Desculpe, voto negativo de mim para coisas que sequestram comentários para funcionalidade real. Um programador de manutenção poderia passar o dia todo tentando descobrir por que códigos como esse estavam imprimindo coisas inesperadas.
MikeKulls

2
@MikeKulls, np. É um filtro de origem, pelo que entendi. Além disso, tendo scripts escritos que verificam todos os módulos que coloco na preparação da produção, não use Smart::Commentsvejo isso também. Mas, para o contador, Smart::Commentsé muito bem comportado como um módulo com escopo , não deve haver comportamento de saída em nenhum módulo que também não use o SC. Portanto, o problema seria isolado para esses escopos com uma declaração de uso . Se você está dizendo que um programador de manutenção não tem responsabilidade de ler o documento nos módulos incluídos, não posso concordar. Ainda assim, obrigado por comentar
Axeman

7
Não estou dizendo que eles não têm responsabilidade, mas provavelmente não é a primeira coisa que procuram. Como nunca vi o módulo Smart Comments antes, eu não sabia por que o código acima estava imprimindo algo. Eu poderia passar dias pulando o comentário e nem processá-lo porque os comentários não deveriam fazer nada. Fazer eles fazerem algo é muito ruim. Eles podem ser usados ​​para gerar documentação, etc, desde que não alterem o comportamento do programa.
MikeKulls

4

Looping:

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

Funcional

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

Mas, por pura elegância, eu teria que escolher o wrang-wrang. Para o meu próprio código, eu escolheria meu foreach. Ou o uso de Dumper da tetro.


3
Não há diferença funcional entre seus usos de foreache map. mapdeve ser usado para a lista de transformações, não no contexto vazio para emular um loop for
Friedo

seria interessante ver os resultados do 'código de bytes' de cada um ... Gostaria de saber se o mapa é mais ou menos eficiente.
Ape-inago 22/07/2009

2

A maneira mais fácil em minhas experiências é apenas usar o Dumpvalue .

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

Funciona como um encanto e você não precisa se preocupar em formatar o hash, pois ele o gera como o depurador Perl (ótimo para depuração). Além disso, o Dumpvalue está incluído no conjunto de módulos Perl, para que você não precise mexer no CPAN se estiver atrás de algum tipo de proxy draconiano (como eu estou no trabalho).


1

Se você quer ser pedante e mantê-lo em uma linha (sem as instruções de uso e o shebang), então eu meio que recuo da resposta do tetromino e sugiro:

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

Não fazer nada de especial além de usar o hash anônimo para pular a variável temp;)


O OP diz que ele tem "meu hash" que precisa ser impresso. Essa resposta é apenas esperteza para seu próprio bem
justintime

A OP esperava fazer isso em uma linha. Estava apenas mostrando uma maneira de fazer uma linha. Então isso é digno de um voto negativo?
Kyle Walsh

1

Anexo um espaço para cada elemento do hash para vê-lo bem:

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

1

Eu realmente gosto de classificar as chaves em um código de linha:

print "$_ => $my_hash{$_}\n" for (sort keys %my_hash);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.