• Publicidad

Cambiar valor array y volcarlo en fichero

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

Cambiar valor array y volcarlo en fichero

Notapor Maku79 » 2018-04-10 06:08 @297

¡Hola de nuevo, "perleros"!

Aquí sigo aprendiendo de este lenguaje y creo que no tengo claras las cosas porque las complico demasiado :roll:

Voy a contar mi nuevo problema (a ver si lo consigo).

Tengo dos ficheros de entrada ambos con el siguiente formato pero con diferente número de líneas:
Fichero1 (sin repeticiones)
codigonumericoA1, nombreA1, codigonumericoB1, nombreB1
codigonumericoA2, nombreA2, codigonumericoB2, nombreB2
codigonumericoA3, nombreA3, codigonumericoB3, nombreB3

Fichero2 (sin repeticiones)
codigonumericoC1, nombreC1, codigonumericoD1, nombreD1
codigonumericoC2, nombreC2, codigonumericoD2, nombreD2

Primero debo buscar el valor del tercer campo de cada linea del primer fichero (nombreB1, nombreB2, nombreB3, etc) en el segundo fichero y entonces sustituir el valor codigonumericoB1, codigonumericoB2, etc. por el correspondiente del fichero 2 (codigonumericoD1, o codigonumericoD2, etc.). No sé si me he podido explicar correctamente...

Una vez sustituido quiero volcarlo en un fichero de salida de forma que quedaría así:

Fichero salida
codigonumericoA1, nombreA1, codigonumericoCORRESPONDIENTE, nombreB1
codigonumericoA2, nombreA2, codigonumericoCORRESPONDIENTE, nombreB2

De momento y tras mucho darle vueltas (seguro que existe un modo más sencillo de hacerlo), he conseguido comparar los nombres (nombreB1 y nombreD1) y si coinciden, sustituir el valor del código correspondiente del fichero2, pero el problema lo tengo cuando quiero volcar la información en un nuevo fichero.

Aquí mi (locura) código: :oops:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use strict;
  3. use autodie;
  4. use diagnostics;
  5. use warnings;
  6.  
  7. my @CRC;                #Array de líneas del fichero2
  8. my @codigo;             #Array de líneas del fichero1
  9.  
  10. my @guardar;            #Array donde guardo los nombres de centro de fichero1
  11. my @codDep;             #Array donde guardo el código centro a sustituir
  12. my @sustituir;          #Array donde guardo el par código, nombre centro de fichero1
  13. my @otro;               #Array donde guardo el nombre de centro de fichero2
  14. my @valor;              #Array donde guardo el código de centro que quiero
  15. my @save;               #Array donde guardo el par código, nombre_centro de fichero2
  16.  
  17. open my $ENTRADA, '<', "fichero1.txt";
  18. open my $OTRO, '<', "fichero2.txt";
  19. open my $SALIDA, '>', "salida.txt";
  20.  
  21. while (my $linea = <$ENTRADA>) {
  22.         chomp $linea;
  23.         @codigo = split /,/, $linea;
  24.         my $elem = "$codigo[3]\n";
  25.         my $ct = "$codigo[2],$codigo[3]\n";
  26.  
  27.         push @sustituir, $ct;   #array con el par código centro, nombre
  28.         push @guardar, $elem;   #array con solo los nombres de centros
  29. }
  30. while (my $linea = <$OTRO>) {
  31.         chomp $linea;
  32.         @CRC = split /,/, $linea;
  33.         my $nombre_CT = "$CRC[3]\n";
  34.         my $elem2 = "$CRC[2],$CRC[3]\n";
  35.  
  36.         push @save, $elem2;     #Tengo el par código, nombre
  37.         push @otro, $nombre_CT; #Tengo el nombre del centro del fichero2
  38. }
  39. my $cosa = scalar(@save);
  40. my $contador = 0;
  41.  
  42. for (my $i=0; $i < $cosa; $i++) {
  43.                 if (grep {$_ eq $otro[$i]} @guardar) {
  44.                         @valor = split /,/, $save[$i];
  45.                         print "\n Codigo a sustituir de fichero2 $valor[0]\n";  #valor que quiero
  46.                         print "Nombre del centro de fichero2 $valor[1]";
  47.                         #####Ahora quiero sustituir
  48.                         my $j = 0;
  49.                         foreach (@sustituir) {
  50.                                 @codDep = split /,/, $sustituir[$j];
  51.                                 $j++;
  52.                                 if ($codDep[1] eq $valor[1]) {
  53.                                         print "Código centro del fichero1 $codDep[0]\n";
  54.                                         print "Nombre centro del fichero1 $codDep[1]";
  55.                                         $codigo[2] = $valor[0]; #sustituimos el valor del código
  56.                                         print "Valor $codDep[0] ya sustituido por $codigo[2] \n";
  57.                                         print $SALIDA join(',', @codigo), "\n";
  58.                                 }
  59.                         }
  60.                         $contador++;
  61.                 }
  62. }
  63. print "Coincidencias totales $contador de $cosa\n";
  64. close $OTRO;
  65. close $ENTRADA;
  66. close $SALIDA;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


El fichero de salida sale con el codigonumericoB1, B2, B3, etc., cambiado, pero el resto de campos son siempre el mismo. De hecho los de la última fila del fichero1. Sé que es porque en @codigo se ha quedado almacenada la última línea tras terminar de leer el primer fichero, pero he intentado varias cosas para que cambie también el resto de campos y no lo consigo.

¿Me he explicado bien? ¿Alguna idea?
¡Muchas gracias por adelantado!
Última edición por Maku79 el 2018-04-10 06:50 @326, editado 5 veces en total
Maku79
Perlero nuevo
Perlero nuevo
 
Mensajes: 14
Registrado: 2018-03-22 06:44 @322

Publicidad

Re: Cambiar valor array y volcarlo en fichero

Notapor explorer » 2018-04-10 06:22 @307

Maku79 escribiste:Primero debo comprobar que el valor del primer fichero nombreB1 sea el mismo que el valor del segundo fichero

No queda claro si estamos buscando una coincidencia a nivel de línea (el nombreB1 de la línea N del primer archivo debe coincidir con el nombreD1 de la misma línea N del segundo archivo), o si nos basta con una coincidencia a nivel de todo el archivo.

Tampoco queda claro si nombreB1, nombreB2... son únicos o pueden repetirse, así como a nombreD1, nombreD2.

Si se repiten, tenemos que tener en cuenta las repeticiones, si no, podemos usar el truco de los hash para guardar la información del segundo archivo que nos interesa, indexada por nombreD1... y luego bastaría con recorrer las líneas del primer archivo buscando coincidencias.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Cambiar valor array y volcarlo en fichero

Notapor Maku79 » 2018-04-10 06:39 @318

¡Hola, explorer!

Antes de nada, gracias por la respuesta y perdón por no haberme explicado correctamente.

En ninguno de los ficheros existen repeticiones, son nombres únicos por línea (nombreB1, nombreB2, nombreD1, nombreD2... solo aparecen una vez) y la comparación es solo a nivel de ese campo (el tercero de la línea), que debe aparecer en cualquier línea, del tercer campo también, del segundo fichero. Espero haber aclarado mi explicación.

He probado con hashes también pero no los controlo todavía :oops:

PD: He editado el primer mensaje intentando aclararlo. :wink:
Maku79
Perlero nuevo
Perlero nuevo
 
Mensajes: 14
Registrado: 2018-03-22 06:44 @322

Re: Cambiar valor array y volcarlo en fichero

Notapor explorer » 2018-04-10 14:27 @644

Pues, entonces... el problema se resuelve igual de fácil que los otros que has planteado en otros hilos.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.18;
  3. use autodie;
  4.  
  5.  
  6. open my $ENTRADA, '<', "fichero1.txt";
  7. open my $OTRO,    '<', "fichero2.txt";
  8. open my $SALIDA,  '>', "salida.txt";
  9.  
  10.  
  11. # Leemos el $OTRO archivo y nos quedamos con su información
  12. my %otro;
  13.  
  14. while (my $linea = <$OTRO>) {
  15.     chomp $linea;
  16.  
  17.     my @campos_del_otro = split /\s*,\s*/, $linea;
  18.  
  19.     $otro{ $campos_del_otro[-1] } = $campos_del_otro[-2];
  20. }
  21.  
  22. close $OTRO;
  23.  
  24. # Leemos el archivo de $ENTRADA, al mismo tiempo que actualizamos el de $SALIDA
  25. my $coincidencias = 0;
  26.  
  27. while (my $linea = <$ENTRADA>) {
  28.     chomp $linea;
  29.  
  30.     my @campos_de_entrada = split /\s*,\s*/, $linea;
  31.  
  32.     # si existe el campo de entrada en el %otro
  33.     if (exists $otro{ $campos_de_entrada[-1] }) {
  34.  
  35.         $coincidencias++;
  36.  
  37.         # modificamos el penúltimo valor con el del %otro
  38.         $campos_de_entrada[-2] = $otro{ $campos_de_entrada[-1] };
  39.  
  40.         say $SALIDA join ", ", @campos_de_entrada;
  41.     }
  42. }
  43.  
  44. close $ENTRADA;
  45. close $SALIDA;
  46.  
  47. say "Coincidencias totales: $coincidencias";
  48.  
  49. __END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Ya ves... con la ayuda de un simple hash, guardamos la información del segundo archivo, y luego solo tenemos que recorrer el primero, y ver si hay coincidencia o no.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Cambiar valor array y volcarlo en fichero

Notapor Maku79 » 2018-04-11 02:25 @142

¡¡Muchas gracias por tu respuesta, explorer!!

¡Cómo me complico la vida, ya lo decía yo...! Al usar arrays, cómo acceder a los campos de los arrays y guardarme los valores, en vez de usar un simple hash, estaba dándole demasiadas vueltas...

Yo ya había probado también un código con hashes, usaba uno para cada fichero, pero no conseguía cambiar los valores, además utilizaba dos hashes, uno para cada fichero y con solo uno veo que es suficiente. Los hashes son todo un reto para mí, no me resulta muy fácil de entender, no pillo bien lo del par "clave/valor", pero bueno, a ver si me pongo a hacer ejercicios de hashes y logro comprenderlos...

Este "$otro{ $campos_de_entrada[-1] }" no sabía que se podía hacer :oops: , sé que accede al último campo del array, y con -2 accedes al penúltimo, pero no se me habría ocurrido nunca...

Ya ves, en 50 líneas, y yo reinventando la rueda... :roll:

¡Muchas gracias, explorer! ¡Funciona a la perfección!

PD: Volveré... :lol:
Maku79
Perlero nuevo
Perlero nuevo
 
Mensajes: 14
Registrado: 2018-03-22 06:44 @322

Re: Cambiar valor array y volcarlo en fichero

Notapor explorer » 2018-04-11 03:47 @199

Maku79 escribiste:Los hashes son todo un reto para mí, no me resulta muy fácil de entender, no pillo bien lo del par "clave/valor", pero bueno, a ver si me pongo a hacer ejercicios de hashes y logro comprenderlos...

Es muy sencillo: piensa que son igual que los array, pero en lugar de usar números como índices, se usa un texto.

Al igual que en los array, los índices (claves) son únicos (no puedes tener dos elementos en el elemento 2 de un array).

De alguna forma, cuando estamos recuperando información desde un hash es como si hiciéramos un bucle por un array para buscar el elemento que nos interesa. Es como tu bucle de las líneas 49 a 59. Pero en un hash tratamos con el texto directamente, no buscamos (ya lo hace Perl por nosotros).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Cambiar valor array y volcarlo en fichero

Notapor Maku79 » 2018-04-11 06:23 @307

Ahí está la clave, en que el índice no es un número, es un texto, eso es lo que me cuesta ver muchas veces pero veo la utilidad del hash a la hora de no tener que buscar por un array un elemento en concreto.

¡¡¡Muchas gracias por tus explicaciones y por la paciencia ante estas preguntas/dudas de novatos!!! :D
Maku79
Perlero nuevo
Perlero nuevo
 
Mensajes: 14
Registrado: 2018-03-22 06:44 @322


Volver a Básico

¿Quién está conectado?

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