Mar Jun 24, 2008 5:19 pm
|
 |
teco000
Perlero Nuevo

|
Registrado: 29 May 2008
Mensajes: 33
Ubicación: Guatemala
|
|
| Cómo agrupar registros de un fichero |
|
|
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 |
|
|
|
|

Mie Jun 25, 2008 3:36 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4100
Ubicación: Valladolid, España
|
|
|
|
|
¿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 |
|
|

Mie Jun 25, 2008 7:11 am
|
 |
kidd
Creador de Perl en Español

|
Registrado: 15 Oct 2003
Mensajes: 1389
Ubicación: México
|
|
|
|
|
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];
} |
|
|

Mie Jun 25, 2008 9:11 am
|
 |
teco000
Perlero Nuevo

|
Registrado: 29 May 2008
Mensajes: 33
Ubicación: Guatemala
|
|
|
|
|
Gracias a los dos, ambas respuestas me son muy útiles.  |
|

Mie Jun 25, 2008 9:59 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4100
Ubicación: Valladolid, España
|
|
|
|
|
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... |
|

Mie Jun 25, 2008 4:18 pm
|
 |
teco000
Perlero Nuevo

|
Registrado: 29 May 2008
Mensajes: 33
Ubicación: Guatemala
|
|
|
|
|
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; |
|
|

Mie Jun 25, 2008 4:41 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4100
Ubicación: Valladolid, España
|
|
|
|
|
Con
| Perl: | @DATA = "$acumtrama"; |
no guardas nada en el array, solo un elemento.
Debes usar push():
O mejor:
| Perl: | if ($bin eq 5555555545){
push @DATA, "$bin $codtrans $valor";
$conteo_B++;
} |
Y luego, hacer el bucle por @DATA:
| Perl: | foreach ( @DATA ) { |
|
|
Mie Jun 25, 2008 5:22 pm
|
 |
teco000
Perlero Nuevo

|
Registrado: 29 May 2008
Mensajes: 33
Ubicación: Guatemala
|
|
|
|
|
| Gracias, ese era mi gran error. Ya funciona |
|
Powered by phpBB © 2001, 2005 phpBB Group
|