• Publicidad

Imprimir en orden claves hash de segundo nivel

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

Re: Imprimir en orden claves hash de segundo nivel

Notapor explorer » 2013-12-27 20:35 @899

Un momento, un momento, un momento...

Las condiciones de poner un 'NaN' ahora son otras... Hay que poner un 'NaN' cuando en la celda contiene un '-'. Y solo en ese caso.

Pero, además... ocurre que por fin nos enteremos de cómo es en realidad las celdas de la hoja: resulta que las filas están "dobladas" (una celda de una fila comparte contenido con la celda que le sigue en la fila de abajo) para las celdas que solo contienen números; y son simples (una celda con número y una celda con un texto) cuando vienen acompañadas de un texto.

Entonces... mal iba a funcionar la expresión regular de esa manera... En realidad, son dos las celdas que hay que leer. Hay que ver si la celda que hay debajo de ella contiene un '-' o no.

La siguiente solución tiene en cuenta todo eso:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.10;                                                     # lo necesitamos para el 'say' y el operador '//'
  3. use strict;
  4. use warnings;
  5. use diagnostics;
  6.  
  7. use Spreadsheet::Read;
  8.  
  9. ## Constantes
  10. my $year  = 2013;
  11. my $ruta  = "/home/modelacion/Escritorio/excel_perl";
  12. my @meses = (
  13.     [ 'Enero',          'January',      31 ],
  14.     [ 'Febrero',        'February',     29 ],
  15.     [ 'Marzo',          'March',        31 ],
  16.     [ 'Abril',          'April',        30 ],
  17.     [ 'Mayo',           'May',          31 ],
  18.     [ 'Junio',          'June',         30 ],
  19.     [ 'Julio',          'July',         31 ],
  20.     [ 'Agosto',         'August',       31 ],
  21.     [ 'Septiembre',     'September',    30 ],
  22.     [ 'Octubre',        'October',      31 ],
  23.     [ 'Noviembre',      'November',     30 ],
  24.     [ 'Diciembre',      'December',     31 ],
  25. );
  26.  
  27. ## Proceso
  28. open my $OUT, '>', 'datos.txt';
  29.  
  30. for my $mes (@meses) {
  31.  
  32.     my ( $mes_spa, $mes_eng, $mes_dias ) = @{$mes};
  33.  
  34.     my $archivo = "$ruta/Inf-WS-$mes_eng$year.xls";
  35.     next if not -e $archivo;                                    # saltamos al siguiente, si no existe archivo de ese mes
  36.  
  37.     my $ref  = ReadData($archivo);;
  38.     my $HOJA = $ref->[1]->{cell};
  39.  
  40.     for my $fila ( 0 .. 23 ) {                                  # son 24 filas dobles
  41.         my @fila;
  42.  
  43.         for my $columna ( 1 .. $mes_dias ) {
  44.  
  45.             my $celda_arriba = $HOJA->[$columna]->[1+2*$fila] // '';
  46.             my $celda_abajo  = $HOJA->[$columna]->[2+2*$fila] // '';
  47.  
  48.             if (index($celda_abajo, '-') != -1) {               # si la parte de abajo contiene un '-'
  49.                 $celda_arriba = 'NaN';                          # 'NaN'deamos la parte de arriba
  50.             }
  51.  
  52.             push @fila, $celda_arriba;
  53.         }
  54.  
  55.         say $OUT "@fila";
  56.     }
  57. }
  58. close $OUT;
Coloreado en 0.006 segundos, usando GeSHi 1.0.8.4
Se procede de la siguiente manera: hacemos un bucle por las 24 filas dobles. No son filas de la hoja, sino filas de datos. Usamos $fila como índice para acceder a la posición que nos interesa (una celda en la parte superior y otra en la inferior).

Si la celda que contiene un número, está compartida con la que le sigue abajo. Ésta última no está definida, pero con el operador '//' la convertimos a un cadena vacía.

Si la celda contiene un número más un texto, el número aparece en la primera celda (igual que el caso anterior), y la celda que le sigue abajo contiene el texto. Entonces, comprobamos si en ese texto aparece un '-' (con la función index()). Si es así, modificamos el valor numérico a 'NaN'.

Las primeras filas que salen:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
2.93 0.58 5.88 5.93 8.6 4.94 1.18 2.44 0.92 6.36 2.58 6.48 1.9 4.68 5.79 3.64 3.37 2.28 5.07 1.93 2.16 3.43 1.24 1.74 1.99 1.33 3.19 1.48 NaN NaN 1.89
2.67 0.68 4.72 6.17 4.75 4.98 0.68 2.07 1.54 7.1 2.58 6.77 0.77 4.38 2.95 3.64 3.37 0.76 3.26 2.22 1.93 4.09 1.59 1.19 1.76 2.82 3.23 1.33 NaN NaN 1.86
1.81 0.99 4.33 7.69 4.89 3.44 1.15 1.73 2.3 6.12 2.58 2.82 1.19 2.95 2.07 3.49 3.37 2.67 1.09 2.29 2.48 4.23 2.19 0.74 1.38 1.44 2.44 0.96 NaN NaN 2.09
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Esta es otra versión, con dos modificaciones: genera por si sola los nombres de los meses en inglés (solo si en el sistema, se ha compilado la configuración regional 'en_IE'. Comprobarlo con el comando locale -a), y siempre genera 31 columnas, que facilita el procesado posterior.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.10;
  3. use strict;
  4. use warnings;
  5. use diagnostics;
  6.  
  7. use Spreadsheet::Read;
  8.  
  9.  
  10. ## Constantes
  11. my $year  = 2013;
  12. my $ruta  = "/home/modelacion/Escritorio/excel_perl";
  13.  
  14. use POSIX qw(strftime locale_h);
  15. my $anterior_locale = setlocale(LC_TIME, "en_IE");                      # pasar a inglés
  16. my @meses = map { strftime '%B', 0,0,0, 1,$_,$year, 0,0,0 } 0 .. 11;    # nombres de los meses, en inglés
  17. setlocale(LC_TIME, $anterior_locale);                                   # volvemos a español
  18.  
  19.  
  20. ## Proceso
  21. open my $OUT, '>', 'datos.txt';
  22.  
  23. for my $mes (@meses) {
  24.  
  25.     my $archivo = "$ruta/Inf-WS-$mes$year.xls";
  26.     next if not -e $archivo;                                    # saltamos al siguiente, si no existe archivo de ese mes
  27.  
  28.     my $ref  = ReadData($archivo);;
  29.     my $HOJA = $ref->[1]->{cell};
  30.  
  31.     for my $fila ( 0 .. 23 ) {                                  # son 24 dobles filas
  32.         my @fila;
  33.  
  34.         for my $columna ( 1 .. 31 ) {
  35.  
  36.             my $celda_arriba = $HOJA->[$columna]->[1+2*$fila] // '';
  37.             my $celda_abajo  = $HOJA->[$columna]->[2+2*$fila] // '';
  38.  
  39.             if (index($celda_abajo, '-') != -1) {               # si la parte de abajo contiene un '-'
  40.                 $celda_arriba = 'NaN';                          # 'NaN'deamos la parte de arriba
  41.             }
  42.  
  43.             push @fila, $celda_arriba;
  44.         }
  45.  
  46.         say $OUT "@fila";
  47.     }
  48. }
  49. close $OUT;
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
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

Publicidad

Anterior

Volver a Básico

¿Quién está conectado?

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