Página 1 de 1

Duplicar hash con éxito

NotaPublicado: 2009-07-03 05:15 @260
por gorkalinux
Hola.

Trato de duplicar un hash de arrays (%fichero1), porque tengo que recorrerlo dos veces haciendo shift() sobre los elementos de los arrays hasta que queda uno, y al final un delete() sobre la key.

El problema es que, como tengo que hacer esto dos veces sobre el mismo hash, pues se me han ocurrido dos opciones, ninguna de las cuales me funciona por motivos que desconozco.

El programa es extensísimo, así que a ver si puedo sintetizar lo importante. Del %fichero2 nos podemos olvidar, que no interesa para la cuestión.

Opción 1:

Pasar la primera vez el array a la función (que realiza los shift() y el delete()) por valor, en lugar de por referencia. Así la primera vez trabajo sobre una copia y la segunda ya puedo eliminar los datos sobre el original:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
funcion(%fichero1,\%fichero2);
funcion(\%fichero1,\%fichero2);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Esto me da un error que traducido viene a decir que "no se pueden utilizar falsos hashes". Creo que no se pueden pasar hashs por valor, corregidme si me equivoco.

Opción 2:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my %fichero1_copia = %fichero1;
use Data::Dumper;
print Dumper \%fichero1;
funcion(\%fichero1,\%fichero2);
print "\n---------------\n";
print Dumper \%fichero1;
print Dumper \%fichero1_copia;
funcion(\%fichero1_copia,\%fichero2);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Esta segunda opción pretendía que el segundo Dumper saliera vacío y el tercero lleno... pero en su lugar obtengo esto:

Código: Seleccionar todo
$VAR1 = {
          'c3' => [
                      [
                        50,
                        52,
                        'CO',
                        '+'
                      ]
                    ],
          'c1' => [
                      [
                        20,
                        22,
                        'COL',
                        '+'
                      ],
                      [
                        10,
                        12,
                        'COL',
                        '+'
                      ],
                      [
                        30,
                        32,
                        'COL',
                        '+'
                      ],
                      [
                        80,
                        82,
                        'COL',
                        '+'
                      ],
                      [
                        90,
                        92,
                        'COL',
                        '+'
                      ]
                    ],
          'c2' => [
                      [
                        40,
                        42,
                        'COM',
                        '+'
                      ],
                      [
                        210,
                        32,
                        'COM',
                        '+'
                      ]
                    ]
        };

---------------

$VAR1 = {};

$VAR1 = {
          'c3' => [
                      [
                        50,
                        52,
                        'CO',
                        '+'
                      ]
                    ],
          'c1' => [
                      [
                        90,
                        92,
                        'COL',
                        '+'
                      ]
                    ],
          'c2' => [
                      [
                        210,
                        32,
                        'COM',
                        '+'
                      ]
                    ]
        };


No entiendo por qué %fichero1_copia no tiene todos los elementos originales. Y si es que los hashs nunca hacen copia, sino que se duplican por referencia (lo que no me sirve), ¿por qué tiene sólo los elementos finales del hash original, en lugar de estar vacío, como el hash original tras ejecutar la función? Es como si los shift() hubieran tenido efecto pero los delete() de las keys no.

En fin... un mar de dudas, espero no haber complicado demasiado mi cuestión. Para simplificar, mi pregunta principal es "cómo duplicar un hash con todo su contenido para trabajar con original y copia de manera independiente".

Un saludo.

Re: Duplicar hash con éxito

NotaPublicado: 2009-07-03 15:26 @684
por netsoul
Creo que tu problema está en la subrutina. Hice un ejemplo para comprobarlo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use strict;
use warnings;
use Data::Dumper;

my %hash = (
    a    => ["jose", "maria", "carlos"],
    b    => ["12", "15", "13"],
    c    => ["cabello", "brazos", "piernas"],
);

my %duplicado_hash = %hash;

print "Original antes de la subrutina:\n", Dumper(\%hash);
hacer(\%hash);
print "Duplicado después de la subrutina:\n", Dumper(\%duplicado_hash);


sub hacer{
 my %h = shift;
# my %h = %{$_[0]};
        while (my ($llave, $valor) =  each %h) {
                while (my $b = shift @{$valor}){
                        # Aquí retorna valores a $b, obtenidos por medio de shift
                }
        }
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Yo utilicé shift. Si te fijas en el código, y reemplazas shift por %{$_[0]}, te darás cuenta que habrá cambios.

Re: Duplicar hash con éxito

NotaPublicado: 2009-07-03 19:55 @871
por explorer
Para copiar estructuras complejas, existe el módulo Clone, que realiza esa tarea de forma muy cómoda:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use Clone qw(clone);

%x = ( a=> [ 1, 2, 3], b => [ 4, 5, 6 ] );

%y = %{ clone(\%x) };

use Data::Dumper;
print Dumper \%y;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Re: Duplicar hash con éxito

NotaPublicado: 2009-07-04 19:16 @844
por Jenda
Lo más sencillo sería cambiar el código para que no destruye el hash.

while (my $item = shift(@array) {

por

for my $item (@array) {

y

while (my ($key, $value) = each %hash) {

por

foreach my $key (keys %hash) {