¿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).

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

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

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á


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

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.


10

Mi favorito: Smart :: Comentarios

use Smart::Comments;
# ...

### %hash

Eso es.


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.


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).


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;)


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

1

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

print "$_ => $my_hash{$_}\n" for (sort keys %my_hash);
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.