[Perl] pequeño script

Gunnar Wolf gwolf@gwolf.cx
Mon, 7 Jul 2003 13:07:03 -0500


John Robeto dijo [Mon, Jul 07, 2003 at 12:02:52PM +0200]:
> Hola a todos.
> Intento hacer una chorrada de script pero no me sale.
> El script debe leer un archivo (txt) que contiene una
> lista de palabras y copiarlas a otro archivo sin que
> se repita ninguna, x ej.
> 
> lista input: coche, casa, perro, perro, pájaro
> output: coche, casa, perro, pájaro
> 
> lo he intentado convirtiendo el archivo de entrada en
> un @array y generando indices de array para la primera
> y segunda cadena, además de un contador $i, algo así:

Antes de ver tu código, te sugiero reescribirlo así:

----------------8<-----------------------
# Conviene manejar errores, no dejar todo al azar
open(ARCHIVO,'<file.txt') or die "No pude abrir file.txt: $!";

%palabras = (); # Creamos un nuevo hash vacío

# Procesamos cada línea del archivo
while (my $linea = <ARCHIVO>) {
    # Según tu ejemplo, cada línea contiene varias palabras
    # separadas por comas
    foreach my $palabra (split(', ', $linea)) {
        # Acá tomamos cada palabra por separado y le creamos una entrada
        # en %palabras
        $palabras{$palabra} = 1;
    }
}
# Ya no necesitamos tener a ARCHIVO abierto - Y sólo a partir de aquí
# necesitamos a SALIDA
close(ARCHIVO);
open(SALIDA,'>fileSal.txt') or die "No pude abrir fileSal.txt: $!";

# ¿No te parece más simple? ¡Con un sólo enunciado cras la lista
# completa y ordenadita!
print SALIDA join("\n", sort keys %palabras);

close(SALIDA);
----------------8<-----------------------

> open (ARCHIVO, "< file.txt");
> open (SALIDA, "> fileSal.txt");
> 
> @lista = <ARCHIVO>;
> 
> $i = 0;             ### contador en cero
> $pal1 = $lista[$0]; ### 1ra palabra de @lista
> $pal2 = $lista[$i]; ### 2da palabra de @lista
> 
> 
> foreach $pal (@lista){
>     if ($pal1 ne $pal2){ ##sin son iguales $i++
> 	$i++;}
>     print SALIDA "$pal2 \n";
> }
> 
> Gracias a quien pueda decirme en qué fallo.

Ahora, yendo a encontrar la falla en tu programa: Se ve que vienes de C
;-) ¿Para qué quieres el contador $i? ¿Qué utilidad te da? Si quieres el
total de palabras, mejor (en mi versión) pide 'scalar keys %palabras' -
'keys %palabras' te da un arreglo con las llaves del hash, y obligarlo a
ser evaluado como 'scalar' te da la cantidad de elementos que tiene.

Acerca de tu programa: 
- ¿Qué tienes en $0? ¿Por qué lo usas como subíndice de $lista?
- Al asignar $lista[$i] a $pal, $i fue ya evaluado - En tu ciclo vas
  incrementando $i, pero $pal2 ya fue asignado, y $i se vuelve un simple
  contador de vueltas. 
- Con la lógica que estás manejando (aún si funcionara ;-) ), sólo
  eliminarías palabras repetidas adyacentes, no si están separadas. En
  todo caso tendrías que hacer dos arreglos e iterar sobre todos los
  elementos de ambos buscando repeticiones.

Saludos,

-- 
Gunnar Wolf - gwolf@gwolf.cx - (+52-55)5630-9700 ext. 1366
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973  F800 D80E F35A 8BB5 27AF