[Perl] Pregunta #3
Salvador Ortiz Garcia
sog@msg.com.mx
14 Mar 2002 17:24:22 -0600
On Wed, 2002-03-13 at 01:54, Luis Guillot wrote:
>=20
> Lo que quiero hacer es algo parecido a lo tuyo, pero no es exacto. Yo ten=
go
> 2 ficheros planos, FICHERO1 y FICHERO2, con datos distintos, pero que tie=
nen
> en com=FAn un campo. Entonces yo quiero comparar este campo com=FAn en lo=
s dos
> ficheros, y los que sean iguales sacarlos.
>=20
> Es decir, por cada campo del FICHERO1, mirar en todo el FICHERO2, y la l=
=EDnea
> que coincida sacar unos datos.
> Esto me implica que por cada entrada del FICHERO1, tengo que recorrer tod=
o
> el FICHERO2. Y no son peque=F1os los ficheros. De ah=ED el alto coste tem=
poral.
>=20
> No me sirve la forma esta de unirlos. Por eso solo se me ha ocurrido lo d=
e
> JavaScript. =BFSe os ocurre algo mejor?
>=20
A ver, y a reserva de que no me queda claro que quieres decir con
"sacarlos", va una soluci=F3n. Supongamos:
Dos archivos de longitud variable F1 y F2, con registros inmensos.=20
Campos separados por ':';
Campos comunes: 2o de F1 y =FAltimo de F2.
Por "sacarlos" quieres imprimir la linea de F2 en que est=E1 el "match".=20
open(F1,"F1") or die 'No puedo bla bla...';
my %hash;
while($_ =3D <F1>) { # Construyo un hash sobre el campo de inter=E9s
chomp; # Play safe
my $dato =3D (split ':')[1]; # 2o campo
$hash{$dato} =3D 'foo'; # 'foo'? Explicaci=F3n m=E1s adelante
}
open(F2,"F2") or die '...';
while($_ =3D <F2>) { # Recorro buscando un "matches"
chomp;
my $dato =3D (split ':')[-1]; # =FAltimo campo
print "$_\n" if $hash{$dato}; # Match!
}
close(F1);
close(F2);
# Voil=E0
Como ver=E1s, s=F3lo tengo que recorrer cada archivo un=E1 sola vez, y no
guardo casi nada en memoria.
Por qu=E9 'foo'? Supongamos que en ese "sacarlos" requieres tambi=E9n datos
de F1, entonces guardas en $hash el/los datos en cuesti=F3n en vez de
'foo'.=20
Pero ojo, si requirieras mucho, digamos en caso extremo, toda el
registro de F1, y usaras "$hash{$dato} =3D $_", terminar=EDas habiendote
comido a memoria, indirectamente, todo F1.
Pero dijimos que era inmenso, as=ED que mejor usamos un 'foo' rarito:
$hash{$dato} =3D tell(F1)-length($_);
Guardamos en el hash la posici=F3n+1 de cada l=EDnea, de forma que cuando l=
a
necesitamos en el segundo while usamos:
if($hash($dato)) { # Match!
seek(F1,$hash($dato)-1,0); # Busco la l=EDnea
my $deF1 =3D <FI>; # La leo
print "$_ | $deF1"; # La de F2 y la de F1!
}=20
Dudas hasta aqu=ED?
Existen a=FAn algoritmos m=E1s eficientes, pero tienen otros requerimientos=
,
espero que =E9ste te ayude.
Saludos.
Salvador Ortiz.
=20