rfm escribiste:En mi actual proyecto accedo secuencialmente a un fichero de log en busca de una fecha en concreto y me preguntaba si no es más eficiente una búsqueda por algún método como quicksort, es decir ir a la mitad del fichero, comparar, si es mayor, ir a la mitad de la mitad anterior, etc...
No es quicksort, es la búsqueda binaria. Podrías hacerlo, pero no creo que te vaya a ayudar mucho. Ora vas a tener que buscar los fines y principios de las líneas cada vez, ora preparar un array con los posiciones de líneas en el fichero. Lo primero va a complicar el código mucho, lo segundo sólo ayuda si buscas más fechas.
Si buscas más fechas puedes recordar las líneas o las posiciones y hacer algo así:
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict
;
use warnings
;
use constant FECHA
=> 3; # en que posición de cada línea es la fecha
sub prepara_datos
{
my ($fichero) = @_;
my %fechas;
open my $IN, '<', $fichero or die "No se puede abrir '$fichero': $^E\n";
my $posicion=0;
while (<$IN>) {
chomp;
my @columns = split /\t/, $_;
$fechas{$columns[FECHA
]} = $posicion;
$posicion = tell($IN);
}
return ( $IN, \%fechas);
}
sub busca_fecha
{
my ($FICHERO, $fechas, $fecha) = @_;
if (exists $fechas->{$fecha}) {
seek($FICHERO, $fechas->{$fecha}, 0
);
my $linea = <$FICHERO>;
chomp($linea);
my @columns = split /\t/, $linea;
return \@columns;
} else {
return; # la fecha no esta en el fichero
}
}
#...
my ($FICHERO, $fechas) = prepara_datos
( $fichero);
foreach my $fecha (@fechas_para_buscar) {
my $datos = busca_fecha
( $FICHERO, $fechas, $fecha);
if (! $datos) {
print "No he encontrado $fecha!\n";
} else {
# haga algo con @$datos
}
}
Coloreado en 0.005 segundos, usando
GeSHi 1.0.8.4
Si el fichero es demasiado grande y no puedes guardar todas las fechas y posiciones en un array, puedes usar BerkeleyDB.pm o AnyDBM_File.pm módulo para poner los datos al disk.
Y si quieres buscar usando otros datos o encontrar todos los datos entre dos fechas o algo similar, puedes importar todos los datos en una base de datos (por ejemplo con DBD::SQLite - es una base de datos en un módulo, no necesitas instalar nada más).
Jenda