¿Cómo puedo imprimir el contenido de un hash en Perl?

167

Sigo imprimiendo mi hash como # de cubos / # asignado. ¿Cómo imprimo el contenido de mi hash?

Sin usar un whilebucle sería más preferible (por ejemplo, una línea sería lo mejor).

Kys
fuente

Respuestas:

253

Datos :: Dumper es tu amigo.

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

saldrá

$VAR1 = {
          'def' => [
                     4,
                     5,
                     6
                   ],
          'abc' => 123
        };
tetromino
fuente
3
el póster original también podría querer examinar las diversas opciones de Data :: Dumper, en particular activar 'Sortkeys' puede ser muy útil
más el
1
@ JonathanDay Me faltaba ese detalle y fue útil. ¡Gracias!
Sos
55
¿Qué significa agregar una barra diagonal delante del%?
champú
16
El operador de barra @shampoo crea una referencia, un poco como el &operador en C y C ++. La razón por la que importa en este contexto es que en Perl, si llama a una función con un valor hash como argumento, ese valor hash se enumera y se expande en múltiples argumentos, por %hsh=("a" => 1, "b" => 2); foo(%hsh);lo que sería equivalente a foo("a", 1, "b", 2). Si, en cambio, desea que la función funcione en el hash, debe pasar una referencia al hash: foo(\%hsh);consulte perldoc.perl.org/perlsub.html#Pass-by-Reference
tetromino el
63

Fácil:

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

Elegante, pero en realidad un 30% más lento (!):

while (my ($k,$v)=each %h){print "$k $v\n"}
Jonathan Graehl
fuente
9
De mala calidad: imprima "@_ \ n" mientras @_ = cada% h
FMc
Creo que quieres decir print "$_ $h{$_}\n" for (keys %h);, $kno existe en ese ejemplo.
Chas. Owens el
44
Además, haga una referencia antes de hacer afirmaciones sobre la eficiencia (o al menos califique el tipo de eficiencia del que está hablando). El forbucle es más rápido que whilehasta al menos 10,000 teclas: gist.github.com/151792
Chas. Owens
1
Por supuesto que tienes razón re: $ k. ¡Pero es más eficiente en Perl 6! :) Sí, también tienes razón en eso. Nunca hubiera pensado optimizar o perfilar mi Perl, pero me alegra saber esto. Por supuesto, cada uno debería ser más eficiente (porque no hay búsqueda adicional de hash en la clave). ¡Pero es ~ 30% más lento!
Jonathan Graehl el
Hola Jonathan Graehl. Lo siento, aún no entiendo. ¿Estás diciendo que cada uno es ~ 30% más lento en función de qué? ¿Es cada vez, para cada situación, una brecha del 30%?
Carlos Sá
37

Aquí cómo puede imprimir sin usar Data::Dumper

print "@{[%hash]}";
Tim Diekmann
fuente
24

Para fines de depuración, a menudo lo usaré YAML.

use strict;
use warnings;

use YAML;

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

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

Resultados en:

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

Otras veces lo usaré Data::Dump. No necesita establecer tantas variables para que salga en un formato agradable del que tiene Data::Dumper.

use Data::Dump = 'dump';

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

Más recientemente, he estado usando Data::Printerpara depurar.

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

(El resultado puede ser mucho más colorido en una terminal)

A diferencia de los otros ejemplos que he mostrado aquí, este está diseñado explícitamente para fines de visualización únicamente. Lo que se muestra más fácilmente si deshace la estructura de una variable vinculada o la de un 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"
    }
}
Brad Gilbert
fuente
tener los colores es "ordenado", pero o estoy haciendo algo mal, o estoy usando "use Data :: Printer; p% var;" no imprime las flechas en hashes, y para un novato como yo eso ayuda
Sos
@Sosi Si miras la salida en la respuesta, verás que no sale =>como esperabas. En su lugar, siempre imprime la clave, varios espacios y luego el valor. Lo que ayuda a un humano a escanear sobre la salida.
Brad Gilbert
12

La respuesta depende de lo que haya en tu hash. Si tienes un hash simple, un simple

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

o

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

funcionará, pero si tiene un hash que está lleno de referencias, tendrá algo que puede recorrer esas referencias y producir una salida sensata. Este recorrido de las referencias normalmente se llama serialización. Hay muchos módulos que implementan diferentes estilos, algunos de los más populares son:

Debido al hecho de que Data::Dumperes parte de la biblioteca principal de Perl, es probablemente la más popular; sin embargo, algunos de los otros módulos tienen cosas muy buenas que ofrecer.

Chas Owens
fuente
10

Mi favorito: Smart :: Comentarios

use Smart::Comments;
# ...

### %hash

Eso es.

Axeman
fuente
55
Lo sentimos, no me votan por cosas que secuestran comentarios para la funcionalidad real. Un programador de mantenimiento podría pasar todo el día tratando de averiguar por qué un código como ese imprimía cosas inesperadas.
MikeKulls
2
@MikeKulls, np. Es un filtro fuente, así que entiendo. Además, después de haber escrito guiones que comprueban cada módulo que puse en preparación de producción que no lo hace use Smart::Comments, también lo veo desde esa perspectiva. Pero para el contador, Smart::Commentsse comporta bastante bien como un módulo de ámbito , no debería haber comportamiento de salida en ningún módulo que no use también SC. Entonces, el problema estaría aislado de esos ámbitos con una declaración de uso . Si está diciendo que un programador de mantenimiento no tiene la responsabilidad de leer el documento en los módulos incluidos, no puedo estar de acuerdo. Aún así, gracias por comentar
Axeman
77
No digo que no tengan una responsabilidad, pero no es probable que sea lo primero que busquen. Nunca antes había visto el módulo de Comentarios inteligentes, no sabría por qué el código anterior estaba imprimiendo algo. Podría pasar días saltándome el comentario y ni siquiera procesarlo porque los comentarios no deberían hacer nada. Hacerlos hacer algo es muy malo. Se pueden usar para generar documentación, etc. siempre que no alteren el comportamiento del programa.
MikeKulls
4

Bucle:

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

Funcional

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

Pero por pura elegancia, tendría que elegir wrang-wrang's. Para mi propio código, elegiría mi foreach. O el uso de Dumper de Tetro.

Paul Nathan
fuente
3
No hay diferencia funcional entre sus usos de foreachy map. mapdebe ser utilizado para las transformaciones de la lista, no en el contexto vacío para emular un ciclo for
Friedo
Sería interesante ver los resultados del 'código de bytes' de cada ... Me pregunto si el mapa es más o menos eficiente.
Ape-inago
2

La forma más fácil en mis experiencias es usar Dumpvalue .

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

Funciona a la perfección y no tiene que preocuparse por formatear el hash, ya que lo genera como lo hace el depurador Perl (ideal para la depuración). Además, Dumpvalue se incluye con el conjunto de stock de módulos Perl, por lo que no tiene que meterse con CPAN si está detrás de algún tipo de proxy draconiano (como si estuviera en el trabajo).

Weegee
fuente
1

Si desea ser pedante y mantenerlo en una línea (sin declaraciones de uso y shebang), entonces me alejaré de la respuesta de tetromino y sugeriré:

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

No hacer nada especial aparte de usar el hash anónimo para omitir la variable temporal;)

Kyle Walsh
fuente
El OP dice que tiene "mi hash" que necesita ser impreso. Esta respuesta es solo inteligencia por sí misma
justintime
OP esperaba hacerlo en una línea. Solo mostraba una forma de hacerlo en una línea. Entonces, ¿eso es digno de un voto negativo?
Kyle Walsh
1

Añado un espacio para cada elemento del hash para verlo bien:

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

Realmente me gusta ordenar las claves en un código de línea:

print "$_ => $my_hash{$_}\n" for (sort keys %my_hash);
labist
fuente