Página 1 de 1

Ordenar array de fechas

NotaPublicado: 2012-06-12 03:37 @193
por ridomil
Buenas, tengo un problema entre pequeño, mediano y grande.

Me explico: necesito ordenar un array de fechas del siguiente formato: 2012/01/01, 2012/01/01, 1985/01/04, 1995/06/07, 2001/02/02. Bien, este sería el array de fechas @fechas. Asociado a este array relleno otros dos arrays: un array de títulos @titulos y un array de nombres de fichero @nombresDeFichero.

El tema es que las posiciones son correlativas en los tres. Es decir la posición $fechas[0] se corresponde con $titulos[0] y con $nombresDeFichero[0]. Así al intercambiar las fechas debemos intercambiar también las posiciones en el otro array. Lo he intentado de este modo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. ##Implementación del algoritmo quicksort
  2. sub colocar {
  3. ##Debemos adaptar un poco el algoritmo para nuestro
  4. ##Caso concreto de comparación de fechas
  5.     guardarLog("ENTRA EN COLOCAR *************************************************** \n\n\n\n\n\n\n");
  6.  
  7.     my ( @fechas, @titulos, @nombreFichero, $b, $t ) = @_;
  8.  
  9.     for ( my $i = 0; $i < $#fechas; $i++ ) {
  10.         guardarLog( "ARRAY DE FECHAS DENTRO DEL QUICKSORT  " . $fechas[$i] . "\n\n\n" );
  11.     }
  12.  
  13.     my $i;
  14.     my $pivote;
  15.     my $valor_pivote;
  16.     my $temp;
  17.     my $tempTitulos;
  18.     my $tempFicheros;
  19.     ##Objeto de tipo dateTime nos servirá para las comparaciones
  20.     my $Strp = new DateTime::Format::Strptime( pattern => '%Y-%m-%d' );
  21.  
  22.     $pivote = $b;
  23.     ##Valor pivote recoge una de las fechas
  24.     ##El valor del pivote con la fecha parseada
  25.     #Vamos a parsear solo para la comparación
  26.     $valor_pivote = $fechas[$pivote];
  27.     my $valor_pivoteParser = $Strp->parser_dateTime($valor_pivote);
  28.  
  29.     for ( $i = $b + 1; $i <= $t; $i++ ) {
  30.         ##Tenemos que parsear cada elemento que se va a comparar
  31.         my $fechaParser = $Strp->parse_datetime( $fechas[$i] );
  32.         ##Tenemos en este punto las dos fechas con un formato adecuado
  33.         if ( ( DateTime->compare( $fechaParser, $valor_pivoteParser ) == -1 ) ) {
  34.  
  35.             #Antes
  36.             #if($fechas[$i] < $valor_pivote){
  37.  
  38.             ##Intercambios, además del intercambio en el array de fechas
  39.             ##Debemos hacer los intercambios en el array de títulos y
  40.             ##Array de nombre fichero
  41.  
  42.             ##Para el array con las fechas
  43.             $pivote++;
  44.             $temp            = $fechas[$i];
  45.             $fechas[$i]      = $fechas[$pivote];
  46.             $fechas[$pivote] = $temp;
  47.  
  48.             ##Para el array con los títulos
  49.             $tempTitulos      = $titulos[$i];
  50.             $titulos[$i]      = $titulos[$pivote];
  51.             $titulos[$pivote] = $temp;
  52.  
  53.             ##Para el array  con los nombres de fichero
  54.             $tempFicheros           = $nombreFichero[$i];
  55.             $nombreFichero[$i]      = $nombreFichero[$pivote];
  56.             $nombreFichero[$pivote] = $temp;
  57.  
  58.         }
  59.     }
  60.     ##Para la ordenación del array de fechas
  61.     $temp            = $fechas[$b];
  62.     $fechas[$b]      = $fechas[$pivote];
  63.     $fechas[$pivote] = $temp;
  64.  
  65.     ##Ordenamos el array de títulos
  66.     $tempTitulos      = $titulos[$b];
  67.     $titulos[$b]      = $titulos[$pivote];
  68.     $titulos[$pivote] = $tempTitulos;
  69.  
  70.     ##Ordenamos el array con los nombres de los ficheros
  71.     $tempFicheros           = $nombreFichero[$b];
  72.     $nombreFichero[$b]      = $nombreFichero[$pivote];
  73.     $nombreFichero[$pivote] = $tempFicheros;
  74.  
  75.     return $pivote;
  76. }
  77.  
  78. ##Implementación del algoritmo quicksort
  79. ##Nota: Los tres parámetros de la llamada inicial a Quicksort son
  80. ## array[0],0,numero_elementos -1
  81. sub quicksort {
  82.     ##Es una modificación del algoritmo de ordenación quicksort
  83.     ##Al tiempo que ordena el array de fechas tiene que ordenar
  84.     ## el array de títulos y el array de nombre fichero
  85.  
  86.     ##Parámetros que recibe
  87.     my ( $fechas, $titulos, $nombreFichero, $b, $t ) = @_;
  88.     guardarLog("ENTRA EN QUICKSORT *************************************************** \n\n");
  89.     guardarLog( "Valor que llega a quicksort del array de fechas " . $fechas[0] );
  90.     guardarLog( "Valor que llega al quicksort del array de títulos " . $titulos[0] );
  91.     guardarLog( "Valor que llega al quicksort del array de nombreFichero " . $nombreFichero[0] );
  92.     guardarLog( "Valor de la variable b " . $b );
  93.     guardarLog( "Valor de la variable t " . $t );
  94.  
  95.     my $pivote;
  96.     if ( $b < $t ) {
  97.         ##Parámetros:
  98.         ##Array de títulos, de fechas y nombre fichero
  99.         $pivote = colocar( @fechas, @titulos, @nombreFichero, $b, $t );
  100.         quicksort( \@fechas, \@titulos, \@nombreFichero, $b,          $pivote - 1 );
  101.         quicksort( \@fechas, \@titulos, \@nombreFichero, $pivote + 1, $t );
  102.     }
  103.  
  104. }
  105.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Pero tengo problemas con los pasos por referencia y con los valores repetidos en el array de fechas... que no sé muy bien cómo tratarlos...

Bueno, como siempre, ¡muchas gracias por la ayuda! Un saludo.

Re: Ordenar array de fechas

NotaPublicado: 2012-06-12 05:54 @287
por explorer
Es muy sencillo...

Debes modificar la subrutina de ordenación para que lo que devuelva sea la lista de índices del array que quieres ordenar. Y una vez que tienes esos índices ordenados, solo te queda reordenar los arrays:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my @indices_ordenados = quicksort(...);

@fechas        = @fechas       [@indices_ordenados];
@titulos       = @titulos      [@indices_ordenados];
@nombreFichero = @nombreFichero[@indices_ordenados];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Re: Ordenar array de fechas

NotaPublicado: 2012-06-12 06:48 @325
por ridomil
Y ¿qué pasará si hay elementos repetidos en el array de fechas?, que sí puede y de hecho va a suceder...

Re: Ordenar array de fechas

NotaPublicado: 2012-06-12 08:51 @410
por explorer
Eso lo tiene que resolver quién esté diseñando la rutina de ordenación... Deberá decidir qué hacer en ese caso. Quizás mirar lo que contienen los otros dos array.

Al final, si el resultado es una lista de índices, el código anterior garantiza que están sincronizados entre los tres array.

Hay otra opción: agrupar la información correspondiente a un índice dentro de un mismo objeto. Así, en lugar de tener tres estructuras de datos separados, solo tendrías una.

Más fácil de ordenar, desde luego.