• Publicidad

Cómo desreferenciar un array

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Cómo desreferenciar un array

Notapor idhard » 2011-10-14 15:19 @680

Hola a todos. Mi problema es sencillo pero no lo puedo solucionar :S ¡Por eso acudo a los que saben! El código es el siguiente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #obtengo los resultados de mi base de datos, la estructura de datos que obtengo es la siguiente :
  2. # $VAR1 = {
  3. #          'codigos' => '7',
  4. #          'nombre_pais' => 'RUSIA FED. - RESTO',
  5. #          'rango_fin' => 7699999999,
  6. #          'id_pais' => 'RUS000',
  7. #          'rango_inicio' => 7800000000
  8. #        };
  9.  
  10. $dataSet = $db->prepare($sql);
  11. $dataSet->execute;
  12. my @rangos = @{$db->selectall_arrayref($sql,{ Slice => {} } ) };
  13.  
  14.  
  15. my $i = 0;
  16. my @rangosTmp ;
  17.  
  18. while ($i <= $#rangos ){
  19.  
  20.     @rangosTmp  = @{ procesarRangoContenedor(\@rangosTmp,$rangos[$i])};
  21.     $i++;
  22.  
  23. }
  24.  
  25. #print Dumper @rangosTmp;
  26.  
  27.  
  28. sub procesarRangoContenedor
  29. {
  30.     my @rangosBuscar = @{ $_[0] };
  31.     my $rangoCompara = $_[1];
  32.  
  33.    
  34.     local $j = 0;
  35.  
  36.     while ($j <= $#rangosBuscarTmp){
  37.         if( $rangoCompara->{rango_inicio} > $rangosBuscar[$j]->{rango_inicio} &&  $rangoCompara->{rango_inicio} <  $rangosBuscar[$j]->{rango_fin} ){
  38.             #aui mi problema con las referencias
  39.             my $rangoResto = $rangosBuscar[$j];
  40.  
  41.  
  42.             #modifica $rangosBuscar tambien!!! ;S
  43.             $rangoResto->{rango_inicio} = $rangoCompara->{rango_fin} + 1;
  44.  
  45.             # rango fin contenedor  = rango inicio contenido - 1
  46.             $rangosBuscar[$j]->{rango_fin} =  $rangoCompara->{rango_inicio} - 1;
  47.  
  48.  
  49.             print Dumper $rangosBuscar[$j];
  50.             print Dumper $rangoResto;
  51.             print Dumper $rangoCompara;
  52.            
  53.  
  54.  
  55.             push(@rangosBuscar,$rangoCompara);
  56.             push(@rangosBuscar,$rangoResto);
  57.             #print Dumper @rangosBuscar;
  58.             die;
  59.             return (\@rangosBuscar);
  60.  
  61.  
  62.         }
  63.  
  64.  
  65.         $j++;
  66.     }
  67.  
  68.     push(@rangosBuscar,$rangoCompara);
  69.     return (\@rangosBuscar);
  70.  
  71.  
  72. #    my @registros
  73.  
  74. }
  75.  
  76.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Bueno, básicamente ese es mi tema. Lo que trato de hacer es simular una tabla virtual que voy a ir modificando (agrandando también) acorde a los registros que obtengo de la base de datos. Una vez finalizada la tabla la voy a insertar en mi base de datos. Pero cuando quiero copiar un registro de esa tabla virtual para poder trabajar con él y agregarlo tengo el problema de las referencias, que no sé cómo solucionarlo.

Espero alguien me tire un salvavidas :D

¡Muchas gracias!
idhard
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2011-10-14 15:06 @670

Publicidad

Re: Cómo desreferenciar un array

Notapor explorer » 2011-10-15 11:38 @526

Bienvenido a los foros de Perl en español, idhard.

A ver... Yo creo que estás haciendo un uso excesivo de referencias y des-referencias en el código. De hecho, me da la sensación de que estoy viendo el código hecho por un programador de C (que el Dios de la biomecánica tenga a Dennis Ritchie en su seno).

Por lo que veo, en el bucle de la línea 18 intentas procesar cada elemento de @rangos, y dejar el resultado en @rangosTmp.

Para mí, sería interesante ver un ejemplo gráfico. Es decir: qué contiene @rangos, qué es lo que devuelven los Dumper... Me gustaría ver con qué estructuras estamos jugando.

Y también me gustaría saber qué es lo que quieres conseguir, más allá de la forma de hacerlo, porque es posible que exista otra forma mejor de hacerlo.

Lo único que puedo ver, de momento, es que en la línea 39 estás copiando la referencia a un hash (almacenado en $rangosBuscar[$j]) a $rangoResto, así que, efectivamente, ocurre lo que indicas en el comentario de la línea 42: modificar uno modifica el otro.

Si creo entender lo que quieres hacer, lo que no quieres es referirte a ese elemento, sino sacar una copia de él, para luego ser insertado en la línea 56 como un elemento nuevo, independiente de $rangosBuscar[$j].

En ese caso, puede usar el módulo Clone o el módulo Storable.

Quedaría algo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.             my $rangoResto = clone($rangosBuscar[$j]);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
(al principio del programa, pones use Clone qw(clone);)

Y ya está: a partir de esa línea, $rangoResto es una copia literal (clonación) de $rangosBuscar[$j], pero independiente.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Cómo desreferenciar un array

Notapor idhard » 2011-10-16 11:09 @506

Hola Explorer,

en principio, gracias por la bienvenida y la pronta respuesta, he seguido el foro en el poco tiempo que empecé con Perl y siempre lo encuentro de mucha utilidad.

En cuanto a mi problema, es muy buena tu interpretación: es exactamente lo que tengo pretendido hacer.

Para ponerte en contexto te comento que se me hace difícil la utilización de módulos que no estén incluidos por defecto en la instalación de Perl ya que el servidor con el que estoy trabajando no cuenta con salida a Internet, por temas de seguridad. Por eso debo instalar todos los paquetes que necesite de forma manual y en algunas ocasiones esto es más un problema que una solución :S.

Mi idea era no entrar en detalles en el desarrollo que tengo que hacer, si no para que me pagan el sueldo :D, pero si estáis interesado aquí mi dilema:

La variable @rangos tiene la siguiente estructura de datos (tan solo los 20 primeros registros de aprox. 40000):

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $VAR1 = {
  2.           'codigos' => '7',
  3.           'nombre_pais' => 'RUSIA FED. - RESTO',
  4.           'rango_fin' => '7999999999',
  5.           'id_pais' => 'RUS000',
  6.           'rango_inicio' => '7000000000'
  7.         };
  8. $VAR2 = {
  9.           'codigos' => '11',
  10.           'nombre_pais' => 'ESTADOS UNIDOS - RESTO',
  11.           'rango_fin' => '1199999999',
  12.           'id_pais' => 'USA000',
  13.           'rango_inicio' => '1100000000'
  14.         };
  15. $VAR3 = {
  16.           'codigos' => '20',
  17.           'nombre_pais' => 'EGIPTO - RESTO',
  18.           'rango_fin' => '2099999999',
  19.           'id_pais' => 'EGY000',
  20.           'rango_inicio' => '2000000000'
  21.         };
  22. $VAR4 = {
  23.           'codigos' => '27',
  24.           'nombre_pais' => 'SUDAFRICA - RESTO',
  25.           'rango_fin' => '2799999999',
  26.           'id_pais' => 'ZAF000',
  27.           'rango_inicio' => '2700000000'
  28.         };
  29. $VAR5 = {
  30.           'codigos' => '30',
  31.           'nombre_pais' => 'GRECIA - RESTO',
  32.           'rango_fin' => '3099999999',
  33.           'id_pais' => 'GRC000',
  34.           'rango_inicio' => '3000000000'
  35.         };
  36. $VAR6 = {
  37.           'codigos' => '31',
  38.           'nombre_pais' => 'HOLANDA - RESTO',
  39.           'rango_fin' => '3199999999',
  40.           'id_pais' => 'NLD000',
  41.           'rango_inicio' => '3100000000'
  42.         };
  43. $VAR7 = {
  44.           'codigos' => '32',
  45.           'nombre_pais' => 'BELGICA - RESTO',
  46.           'rango_fin' => '3299999999',
  47.           'id_pais' => 'BEL000',
  48.           'rango_inicio' => '3200000000'
  49.         };
  50. $VAR8 = {
  51.           'codigos' => '33',
  52.           'nombre_pais' => 'FRANCIA - RESTO',
  53.           'rango_fin' => '3399999999',
  54.           'id_pais' => 'FRA000',
  55.           'rango_inicio' => '3300000000'
  56.         };
  57. $VAR9 = {
  58.           'codigos' => '34',
  59.           'nombre_pais' => 'ESPA▒A - RESTO',
  60.           'rango_fin' => '3499999999',
  61.           'id_pais' => 'ESP000',
  62.           'rango_inicio' => '3400000000'
  63.         };
  64. $VAR10 = {
  65.            'codigos' => '36',
  66.            'nombre_pais' => 'HUNGRIA - RESTO',
  67.            'rango_fin' => '3699999999',
  68.            'id_pais' => 'HUN000',
  69.            'rango_inicio' => '3600000000'
  70.          };
  71. $VAR11 = {
  72.            'codigos' => '39',
  73.            'nombre_pais' => 'ITALIA - RESTO',
  74.            'rango_fin' => '3999999999',
  75.            'id_pais' => 'ITA000',
  76.            'rango_inicio' => '3900000000'
  77.          };
  78. $VAR12 = {
  79.            'codigos' => '40',
  80.            'nombre_pais' => 'RUMANIA - RESTO',
  81.            'rango_fin' => '4099999999',
  82.            'id_pais' => 'ROM000',
  83.            'rango_inicio' => '4000000000'
  84.          };
  85. $VAR13 = {
  86.            'codigos' => '41',
  87.            'nombre_pais' => 'SUIZA - RESTO',
  88.            'rango_fin' => '4199999999',
  89.            'id_pais' => 'CHE000',
  90.            'rango_inicio' => '4100000000'
  91.          };
  92. $VAR14 = {
  93.            'codigos' => '43',
  94.            'nombre_pais' => 'AUSTRIA - RESTO',
  95.            'rango_fin' => '4399999999',
  96.            'id_pais' => 'AUT000',
  97.            'rango_inicio' => '4300000000'
  98.          };
  99. $VAR15 = {
  100.            'codigos' => '44',
  101.            'nombre_pais' => 'REINO UNIDO - RESTO',
  102.            'rango_fin' => '4499999999',
  103.            'id_pais' => 'GBR000',
  104.            'rango_inicio' => '4400000000'
  105.          };
  106. $VAR16 = {
  107.            'codigos' => '45',
  108.            'nombre_pais' => 'DINAMARCA - RESTO',
  109.            'rango_fin' => '4599999999',
  110.            'id_pais' => 'DNK000',
  111.            'rango_inicio' => '4500000000'
  112.          };
  113. $VAR17 = {
  114.            'codigos' => '46',
  115.            'nombre_pais' => 'SUECIA - RESTO',
  116.            'rango_fin' => '4699999999',
  117.            'id_pais' => 'SWE000',
  118.            'rango_inicio' => '4600000000'
  119.          };
  120. $VAR18 = {
  121.            'codigos' => '47',
  122.            'nombre_pais' => 'NORUEGA - RESTO',
  123.            'rango_fin' => '4799999999',
  124.            'id_pais' => 'NOR000',
  125.            'rango_inicio' => '4700000000'
  126.          };
  127. $VAR19 = {
  128.            'codigos' => '48',
  129.            'nombre_pais' => 'POLONIA - RESTO',
  130.            'rango_fin' => '4899999999',
  131.            'id_pais' => 'POL000',
  132.            'rango_inicio' => '4800000000'
  133.          };
  134. $VAR20 = {
  135.            'codigos' => '49',
  136.            'nombre_pais' => 'ALEMANIA - RESTO',
  137.            'rango_fin' => '4999999999',
  138.            'id_pais' => 'DEU000',
  139.            'rango_inicio' => '4900000000'
  140.          };
  141.  
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


Una vez que obtengo estos resultados, los debo procesar uno a uno. El resultado de este proceso, como tu mencionas, lo quería ubicar en la variable @rangosTmp con la subrutina procesarRangoContenedor.

A procesarRangoContenedor le pasaría dos variables @rangosTmp (sería mi tabla virtual donde voy procesando los rangos que obtengo) y $rangos[$i] que es el registro que proceso.

$rangos[$i] tiene la siguiente estructura de datos

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $VAR1 = {
  2.           'codigos' => '7',
  3.           'nombre_pais' => 'RUSIA FED. - RESTO',
  4.           'rango_fin' => '7999999999',
  5.           'id_pais' => 'RUS000',
  6.           'rango_inicio' => '7000000000'
  7.         };
  8.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El problema de la des-referencia surge porque necesito copiar el registro que estoy iterando en mi subrutina para poder agregarlo posteriormente a @rangosTmp con algunas modificaciones. La solución del Clone es lo que buscaba, pero como te comenté anteriormente la utilización de módulos se me dificulta :S.

Muchas gracias por tu tiempo.

Saludos.
idhard
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2011-10-14 15:06 @670

Re: Cómo desreferenciar un array

Notapor explorer » 2011-10-16 11:30 @521

Ningún problema: puedes usar el módulo Storable, que viene incluido en las distribuciones de Perl, desde el Perl v5.7.3.

Hace unos años me encontré con el mismo problema. Lo que hice fue decirle al jefe que salía un momento de la empresa, para ir al cibercafé de la esquina, ya que el proxy empresarial que teníamos no nos dejaba acceder a Internet (o al menos, a donde yo necesitaba acceder). Fui para allá, bajé los ficheros a una memoria USB, y volví.

Más adelante aprendí que hay una manera, mediante la herramienta cpanmini, de tener una copia de TODO CPAN (bueno, solo las versiones más modernas de todas las distribuciones). Entonces lo metes en un DVD y te lo llevas al trabajo. Lo copias al disco duro y lo metes en un directorio. Solo te queda decirle al comando cpan o cpanp que, en vez de ir a buscar los módulos a Internet, que mire en ese directorio. Listo. Y el jefe no dijo nada, porque se resolvió el problema en un rato. De otra manera, hubiera estado programando durante un par de días, algo que YA estaba hecho (el módulo que instalé).

Hoy en día, con las tarifas de datos de acceso 3G, ya no es necesario: te llevas tu portátil al trabajo y si necesitas bajarte algo, pues lo haces a través de él (o del teléfono móvil, da igual :) )
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Cómo desreferenciar un array

Notapor idhard » 2011-10-17 08:41 @403

Hola, explorer. Con el módulo Storable ¡pude resolver el problema! Muchas gracias. Ahora, no entiendo cómo, para algo tan simple como copiar un valor, hace falta un módulo. Investigaré más al respecto.

Muchas gracias.
idhard
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2011-10-14 15:06 @670

Re: Cómo desreferenciar un array

Notapor explorer » 2011-10-17 09:43 @446

Es que no se trata de 'un' valor, en el sentido que tiene Perl de lo que es un escalar, sino que se trata de una estructura (es un hash) con más de un elemento. Hacer una copia de ese hash equivale a decir que hay que copiar todos sus claves y sus correspondientes valores.

Si solo fuera ese el caso (siempre un hash), no necesitarías ningún módulo. Con algo como esto:

my $rangoResto = { %{ $rangosBuscar[$j] };

te es suficiente para crear una referencia a un nuevo hash (anónimo), cuyo contenido es el mismo que el del hash referenciado por $rangosBuscar[$j] (el %{} "despliega" todos los valores del hash, y con las llaves externas, creamos un nuevo hash).

Pero... fíjate que esta solución solo te sirve si te comprometes para el futuro en mantener los elementos de @rangosBuscar siempre como referencias a hashes simples.

Imagínate que un día cambias de parecer, y decides que, en lugar de usar dos claves dentro de ese hash, rango_inicio y rango_fin, decides tener una sola llamada rango, que sea una referencia a un array, cuyo primer elemento sea el inicio del rango y el segundo, el final. Entonces, ya tienes una estructura compleja de datos (un hash que contiene a su vez un array). La solución anterior ya no te vale. En cambio, con Storable, seguiría funcionando.

Ahora puedes decidir si quieres seguir manteniendo Storable por si el programa sigue evolucionando, o prefieres la solución "rápida" que te propongo ahora.

P.D. En otros lenguajes existe este mismo problema: no es obvio el obtener una "copia" de un objeto o de una estructura compleja de datos, salvo que el operador de asignación '=' esté sobrecargado y ejecute alguna operación de clonación del objeto o de la estructura.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados