2009-11-30 12 views
50

Me gustaría entender correctamente los hashes en Perl. He tenido que usar Perl intermitentemente durante bastante tiempo y, sobre todo cuando tengo que hacerlo, está relacionado principalmente con el procesamiento de texto.¿Cuál es la diferencia entre una referencia hash y hash en Perl?

Y cada vez, tengo que lidiar con hashes, se ensucia. Encuentro la sintaxis muy críptica para hashes

Una buena explicación de hash y referencias hash, sus diferencias, cuando sean requeridas, etc. serían muy apreciadas.

+35

_ * te da una manzana * _ pretenden que es un hash. _ * manos que escribiste instrucciones para una manzana en la nevera * _ eso es una referencia hash. –

+2

Puede consultar el capítulo de _Learning Perl_ sobre hashes. –

+0

@ ~ curandero: Desearía que hubiera sido una respuesta en lugar de un comentario para poder votarte correctamente. –

Respuesta

78

Un hash simple está cerca de una matriz. Sus inicializaciones incluso se ven similares.En primer lugar la matriz:

@last_name = (
    "Ward", "Cleaver", 
    "Fred", "Flintstone", 
    "Archie", "Bunker" 
); 

Ahora vamos a representar la misma información con un hash (matriz alias asociativo):

%last_name = (
    "Ward", "Cleaver", 
    "Fred", "Flintstone", 
    "Archie", "Bunker" 
); 

pesar de que tienen el mismo nombre, la matriz @last_name y el hash %last_name son completamente independientes .

Con la matriz, si queremos saber el apellido de Archie, tenemos que realizar una búsqueda lineal:

my $lname; 
for (my $i = 0; $i < @last_name; $i += 2) { 
    $lname = $last_name[$i+1] if $last_name[$i] eq "Archie"; 
} 
print "Archie $lname\n"; 

Con el hash, que es mucho más sintácticamente directa:

print "Archie $last_name{Archie}\n"; 

Say queremos representar la información con solo una estructura un poco más rica:

  • Cleaver (apellido)
    • Ward (nombre de pila)
    • junio (primer nombre del cónyuge)
  • Picapiedra
    • Fred
    • Wilma
  • Bunker
    • Archie
    • Edith

Antes de referencias llegó, los hashes de valores clave planas eran de lo mejor que podíamos hacer, pero las referencias permiten

my %personal_info = (
    "Cleaver", { 
     "FIRST", "Ward", 
     "SPOUSE", "June", 
    }, 
    "Flintstone", { 
     "FIRST", "Fred", 
     "SPOUSE", "Wilma", 
    }, 
    "Bunker", { 
     "FIRST", "Archie", 
     "SPOUSE", "Edith", 
    }, 
); 

Internamente, las claves y los valores de %personal_info son todos escalares, pero los valores son un tipo especial de referencias hash escalares, creadas con {}. Las referencias nos permiten simular hashes "multidimensionales". Por ejemplo, podemos llegar a Wilma a través

$personal_info{Flintstone}->{SPOUSE} 

Tenga en cuenta que Perl nos permite omitir flechas entre los subíndices, por lo que la anterior es equivalente a

$personal_info{Flintstone}{SPOUSE} 

Eso es un montón de escribir si quieres saber más sobre Fred, por lo que podría agarrar una referencia como una especie de cursor:

$fred = $personal_info{Flintstone}; 
print "Fred's wife is $fred->{SPOUSE}\n"; 

Debido $fred en el fragmento anterior es una hashref, la flecha es necesario.Si lo deja fuera, pero con prudencia habilitado use strict para ayudarle a coger este tipo de errores, el compilador se quejará:

Global symbol "%fred" requires explicit package name at ... 

referencias Perl son similares a los punteros en C y C++, pero nunca puede ser nulo. Los punteros en C y C++ requieren desreferenciación y también lo hacen las referencias en Perl.

Los parámetros de las funciones C y C++ tienen una semántica de paso a paso: son solo copias, por lo que las modificaciones no se transmiten a la persona que llama. Si desea ver los cambios, debe pasar un puntero. Usted puede obtener este efecto con referencias en Perl:

sub add_barney { 
    my($personal_info) = @_; 

    $personal_info->{Rubble} = { 
     FIRST => "Barney", 
     SPOUSE => "Betty", 
    }; 
} 

add_barney \%personal_info; 

Sin la barra invertida, add_barney habría conseguido una copia que ha desechado tan pronto como los sub devoluciones.

Tenga en cuenta también el uso de la "coma de grasa" (=>) anterior. Automatiza la cadena a su izquierda y hace que las inicializaciones de hash sean menos ruidosas sintácticamente.

+0

Dejar caer por 7 años más tarde para tener en cuenta que C y C++ permiten pasar por referencia sin el uso de un puntero. 'void f (DataType & arg)' pasa 'arg' por referencia, y no requiere desreferencia para acceder o modificar. –

+0

@JimV Entonces pasa una _reference_, declarada con '&', que es un 'tipo de' alias. La semántica _is_ pasa por valor. – zdim

+0

Una gran publicación :). Un comentario: tal vez una nota de advertencia sería digno de que @ @ _ aliases argumentos, por lo que uno puede cambiarlos desde el sub (a excepción de las teclas hash)? – zdim

10

A hash es un tipo de datos básico en Perl. Utiliza claves para acceder a sus contenidos.

A hash ref es la abreviatura de referencia a un hash. Las referencias son escalares, que son valores simples. Es un valor escalar que contiene esencialmente, un puntero al propio hash .

Enlace: difference between hash and hash ref in perl - Ubuntu Forums

Una diferencia es también en la sintaxis para borrar. Al igual que C, Perl funciona así para los hashes:

delete $hash{$key}; 

y de referencias Hash

delete $hash_ref->{$key}; 

El Perl Hash Howto es un gran recurso para entender hash frente Hash con referencias Hash

También hay otro enlace here that has more information on perl and references.

6

Consulte perldoc perlreftut que también se puede acceder desde la línea de comando de su computadora.

Una referencia es un valor escalar que se refiere a una matriz completa o a un hash completo (oa casi cualquier otra cosa). Los nombres son un tipo de referencia con el que ya estás familiarizado. Piensa en el presidente de los Estados Unidos: una bolsa de sangre y huesos desordenada e inconveniente. Pero para hablar de él, o para representarlo en un programa de computadora, todo lo que necesita es la cadena escalar fácil y conveniente "Barack Obama".

Las referencias en Perl son como nombres de matrices y hash. Son nombres internos y privados de Perl, por lo que puede estar seguro de que no son ambiguos. A diferencia de "Barack Obama", una referencia solo se refiere a una cosa, y usted siempre sabe a qué se refiere. Si tiene una referencia a una matriz, puede recuperar toda la matriz de ella. Si tiene una referencia a un hash, puede recuperar el hash completo. Pero la referencia sigue siendo un valor escalar fácil y compacto.

+0

@ mjp66 La parte esencial de la respuesta es usar 'perldoc perlreftut' que se instala junto con' perl' en la computadora del OP. Ese es siempre el documento más preciso para la * versión específica de perl * que está utilizando el OP. El enlace solo está incluido como cortesía. Entonces, en ese sentido, las URL de documentación de Perl son solo referencias. El contenido en el enlace puede cambiar, pero el enlace siempre apuntará al "Tutorial de referencias de Perl". No todos los enlaces son creados iguales. FYI. –

15

La siguiente muestra cómo se puede utilizar un hash y una referencia a un hash:

my %hash = (
    toy => 'aeroplane', 
    colour => 'blue', 
); 
print "I have an ", $hash{toy}, " which is coloured ", $hash{colour}, "\n"; 

my $hashref = \%hash; 
print "I have an ", $hashref->{toy}, " which is coloured ", $hashref->{colour}, "\n"; 

Véase también perldoc perldsc.

+8

Personalmente, me pareció confuso ver el término '% hash' para describir un hash. Puede ser una buena idea volver a etiquetar su '% hash' como'% favorite' solo para llevar el punto a casa. La declaración de impresión sería algo así como 'imprimir' Mi juguete favorito es el $ favorite {toy} ";' – Zaid

Cuestiones relacionadas