Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Cómo agrupar registros de un fichero

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico
Mensaje Mar Jun 24, 2008 5:19 pm
teco000
Perlero Nuevo
Perlero Nuevo
Registrado: 29 May 2008
Mensajes: 33
Ubicación: Guatemala
Cómo agrupar registros de un fichero Responder citando

Saludos, me pueden ayudar, estoy recorriendo un archivo, del cual tengo que sacar un resumen, no sé si existe alguna función, o lo tengo que meter a una matriz, les mando un ejemplo de como está el fichero:

Líneas que trae el archivo:
Código:
49204032   00000    45.40    20080505
49204032   00000    45.40    20080505
49204032   20000    45.40    20080505
49204032   20000    45.40    20080505
49204032   20000    45.40    20080505
49204030   00000    45.40    20080505
49204030   00000    45.40    20080505
49204030   00000    45.40    20080505
49204031   10000    45.40    20080505
49204031   20000    45.40    20080505
49204031   10000    45.40    20080505
Resumen: tiene que quedar así
Código:
49204032   00000     90.80   2
49204032   20000    136.20   3
49204030   00000    136.20   3
49204031   10000     90.80   2
49204031   20000     45.40   2
Mensaje Mie Jun 25, 2008 3:36 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4100
Ubicación: Valladolid, España
Responder citando

¿Es importante el orden de salida de las líneas?

Para agrupar líneas, lo mejor es usar los hash, aunque también se puede hacer leyendo línea a línea:

Perl:
        1 #!/usr/bin/perl
        2
        3 $total  = 0;
        4 $numero = 0;
        5 $anterior_codigo = '';
        6
        7 sub pinta_resumen {
        8     print  "$anterior_codigo";
        9     printf "%10.2f%4d\n", $total, $numero;
       10 }
       11
       12 foreach ( sort <DATA> ) {
       13
       14     ( $codigo1, $codigo2, $cantidad ) = split;
       15     $codigo = "$codigo1   $codigo2";
       16
       17     if ( $codigo ne $anterior_codigo ) {
       18         if ( $anterior_codigo ) {
       19             pinta_resumen;
       20             $total = $numero = 0;
       21         }
       22         $anterior_codigo = $codigo;
       23     }
       24     $total += $cantidad;
       25     $numero++;
       26 }
       27 pinta_resumen;
       28
       29
       30 __DATA__
       31 49204032   00000    45.40    20080505
       32 49204032   00000    45.40    20080505
       33 49204032   20000    45.40    20080505
       34 49204032   20000    45.40    20080505
       35 49204032   20000    45.40    20080505
       36 49204030   00000    45.40    20080505
       37 49204030   00000    45.40    20080505
       38 49204030   00000    45.40    20080505
       39 49204031   10000    45.40    20080505
       40 49204031   20000    45.40    20080505
       41 49204031   10000    45.40    20080505
Código:
49204030   00000    136.20   3
49204031   10000     90.80   2
49204031   20000     45.40   1
49204032   00000     90.80   2
49204032   20000    136.20   3
Mensaje Mie Jun 25, 2008 7:11 am
kidd
Creador de Perl en Español
Creador de Perl en Español
Registrado: 15 Oct 2003
Mensajes: 1389
Ubicación: México
Responder citando

Veamos, aquí mi intento usando hash.

Perl:
my @DATA = (
'49204032   00000    45.40    20080505',
'49204032   00000    45.40    20080505',
'49204032   20000    45.40    20080505',
'49204032   20000    45.40    20080505',
'49204032   20000    45.40    20080505',
'49204030   00000    45.40    20080505',
'49204030   00000    45.40    20080505',
'49204030   00000    45.40    20080505',
'49204031   10000    45.40    20080505',
'49204031   20000    45.40    20080505',
'49204031   10000    45.40    20080505',
);


my %Data;

for my $data ( @DATA ) {

    my ($cod1, $cod2, $count) = split /\s+/, $data;

    my $key = $cod1." ".$cod2;

    if( $Data{$key} ){
        $Data{$key}[0] += $count;
        $Data{$key}[1]++;
    }
    else{
        $Data{$key} = [$count,1];
    }

}


for my $key( sort keys %Data ){
    print $key;
    printf "%10.2f%4d\n", $Data{$key}[0], $Data{$key}[1];

}
Mensaje Mie Jun 25, 2008 9:11 am
teco000
Perlero Nuevo
Perlero Nuevo
Registrado: 29 May 2008
Mensajes: 33
Ubicación: Guatemala
Responder citando

Gracias a los dos, ambas respuestas me son muy útiles. Very Happy
Mensaje Mie Jun 25, 2008 9:59 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4100
Ubicación: Valladolid, España
Responder citando

Esta es mi solución usando arrays:
Perl:
#!/usr/bin/perl

while ( <DATA> ) {
    ( $codigo1, $codigo2, $cantidad ) = split;
    $tabla[$codigo1][$codigo2][0] += $cantidad;
    $tabla[$codigo1][$codigo2][1] ++;
}
for $x ( 0 .. $#tabla ) {
    next if !exists $tabla[$x];
    for $y ( 0 .. $#{$tabla[$x]} ) {
        next if !exists $tabla[$x][$y];
        printf "%s   %05d%10.2f%4d\n", $x, $y, $tabla[$x][$y][0], $tabla[$x][$y][1];
    }
}
__DATA__
49204032   00000    45.40    20080505
49204032   00000    45.40    20080505
49204032   20000    45.40    20080505
49204032   20000    45.40    20080505
49204032   20000    45.40    20080505
49204030   00000    45.40    20080505
49204030   00000    45.40    20080505
49204030   00000    45.40    20080505
49204031   10000    45.40    20080505
49204031   20000    45.40    20080505
49204031   10000    45.40    20080505
aunque... es mejor no abusar de este tipo de engendros...
Mensaje Mie Jun 25, 2008 4:18 pm
teco000
Perlero Nuevo
Perlero Nuevo
Registrado: 29 May 2008
Mensajes: 33
Ubicación: Guatemala
Responder citando

Saludos, tengo otro problema, con el siguiente código lo meto a un array:
Perl:
if ($bin == 5555555545){
    $acumtrama = "$acumtrama$bin $codtrans $valor\n";
    @DATA = "$acumtrama";
    $conteo_B++;
}

que me da este resultado al momento de ver el array,
Código:
49204032   00000    45.40    20080505
49204032   00000    45.40    20080505
49204032   20000    45.40    20080505
49204032   20000    45.40    20080505
49204032   20000    45.40    20080505
49204030   00000    45.40    20080505
49204030   00000    45.40    20080505
49204030   00000    45.40    20080505
49204031   10000    45.40    20080505
49204031   20000    45.40    20080505
49204031   10000    45.40    20080505


Luego aplico la solución que me dieron pero no me agarra el array como espero.

Perl:
sub pinta_resumen {
       print  "$anterior_codigo";
       printf "%10.2f%4d\n", $total, $numero;
        }
foreach ( sort <@DATA> ) {
      ( $codigo1, $codigo2, $cantidad ) = split;
      $codigo = "$codigo1   $codigo2";
            if ( $codigo ne $anterior_codigo ) {
               if ( $anterior_codigo ) {
                   pinta_resumen;
                    $total = $numero = 0;
                }
                $anterior_codigo = $codigo;
            }
            $total += $cantidad;
            $numero++;
        }
        pinta_resumen;
Mensaje Mie Jun 25, 2008 4:41 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4100
Ubicación: Valladolid, España
Responder citando

Con
Perl:
@DATA = "$acumtrama";

no guardas nada en el array, solo un elemento.

Debes usar push():
Perl:
push @DATA, $acumtrama;

O mejor:
Perl:
if ($bin eq 5555555545){
    push @DATA, "$bin $codtrans $valor";
    $conteo_B++;
}

Y luego, hacer el bucle por @DATA:
Perl:
foreach ( @DATA )  {
Mensaje Mie Jun 25, 2008 5:22 pm
teco000
Perlero Nuevo
Perlero Nuevo
Registrado: 29 May 2008
Mensajes: 33
Ubicación: Guatemala
Responder citando

Gracias, ese era mi gran error. Ya funciona
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico Todas las horas son GMT - 6 Horas
Página 1 de 1



Powered by phpBB © 2001, 2005 phpBB Group