Corte de control
1. Objetivo:
El objetivo de este artículo es describir una forma simple y prolija de implementar un algoritmo de corte de control.2. Introducción:
2.1. ¿Qué es el corte de control?
El corte de control es un proceso en el cual partiendo de registros ordenados por el valor de uno o más campos, (denominados campos clave o llave o criterio de ordenamiento) se los procesa en categorías determinadas por los criterios de ordenamiento.
En otras palabras, se procesa un conjunto ordenado de registros en subconjuntos determinados por los criterios de orden.
2.2. ¿Para qué se podría aplicar un corte de control?
La aplicación más común para la cuál se realiza el corte de control es para generar reportes que acumulen cantidades y/o importes.
Supongamos que somos un ente regulador de supermercados y aplicamos varios impuestos por provincia, por cada cadena.
Deseamos saber cuánto se recauda por provincia, por impuestos para cada cadena de supermecado ubicadas en todo el país.
A cada cadena se le pueden aplicar uno o varios impuestos diferentes, se desea contabilizar la cantidad de impuestos y el importe total que pagará cada cadena en cada provincia.
Para esto queremos generar un informe a partir del archivo que recibimos una vez por mes con la recaudación.
3. Estructura del algoritmo:
Esta sería la estructura propuesta:
while(condicion_fin_recorrido)
{
clave1_anterior = clave1Actual
[inicializar contadores para el primer corte]
while(condicion_fin_recorrido AND clave1_anterior == clave1Actual)
{
clave2_anterior = clave2Actual
[inicializar contadores para el segundo corte]
while(condicion_fin_recorrido AND clave1_anterior == clave1Actual
AND clave2_anterior
== clave2Actual)
{[incrementar contadores del segundo corte]
[escribir detalle del segundo corte]
[avanzar_lectura]
}
[escribir totales acumulados del segundo corte]
[incrementar contadores del primer corte]
}
[escribir totales acumulados del primer corte]
[incrementar contadores generales]
}
[escribir totales generales]
Vamos a analizarla:
- Recordemos la precondición. La lista o el archivo debe venir ordenado/a por los criterios que usaremos para realizar el corte de control.
- Realizar un corte de control significa que vamos a agrupar y acumular por un criterio determinado, esto significa que mientras la clave sea la misma, estaremos en ese corte. Para esto necesitamos recordar la clave del registro anterior. Esto lo realizamos mediante variables que podemos llamar “claveNAnterior”, donde N un número que significa que clave es, la primera “1”, la segunda “2”, la enésima “N”; otra nomeclatura más clara es el nombre de esa clave, por ejemplo si la clave es “provincia”, la variable se llamará “provinciaAnterior”.
- Un while para la condición de fin de recorrido (preguntaremos por not EOF si es un archivo O si hay más elementos si es una lista), luego tenemos un while por cada corte de control. Notemos que en cada while se arrastra la condición del while anterior y se le agrega con un operador lógico AND la condición del nuevo corte de control.
- El incremento de lectura se realiza dentro del while más interno. Ahí es donde debemos avanzar la lectura del archivo o la lista.
- Dentro de cada corte tendremos acumuladores y contadores que incrementaremos.
- Estos contadores y acumuladores lo debemos inicializar arriba del while correspondiente al corte de control donde serán incrementados.
- De igual manera, las claves anteriores se deben asignar en el mismo lugar.
- Cuando se sale de un while es porque terminamos el corte determinado, es ahí donde se pueden imprimir los totales acumulados.
- La condición de fin de recorrido se da después del avance de lectura que se hace en un sólo lugar, dentro del while más interno. Cuando está condición se da se sale de todos los whiles porque todos arrastran esta condición.
- Finalmente cuando se sale del último while se tienen los totales generales acumulados.
4. Ejemplo de implementación:
Veamos como implementamos lo que acabamos de detallar.
Estos son los datos que tenemos:
Lista ordenada por Provincia - Impuesto | |||
Provincia | Cadena | Impuesto | importe |
Buenos Aires | Cadena1 | i1 | 10 |
Buenos Aires | Cadena1 | i2 | 20 |
Buenos Aires | Cadena2 | i1 | 30 |
CABA | Cadena1 | i1 | 20 |
CABA | Cadena1 | i2 | 30 |
CABA | Cadena2 | i1 | 60 |
CABA | Cadena2 | i2 | 50 |
Mendoza | Cadena1 | i1 | 20 |
Mendoza | Cadena2 | i2 | 30 |
Este es el reporte solicitado:
Prov. : | Buenos Aires | |||
Cadena: | Cadena1 | |||
Cantidad Impuestos | 2 | importe | 30 | |
Cadena: | Cadena2 | |||
Cantidad Impuestos | 1 | importe | 30 | |
Cant. Cadenas: | 2 | importe: | 60 | |
Prov. : | CABA | |||
Cadena: | Cadena1 | |||
Cantidad Impuestos | 2 | importe | 50 | |
Cadena: | Cadena2 | |||
Cantidad Impuestos | 2 | importe | 110 | |
Cant. Cadenas: | 2 | importe: | 160 | |
Prov. : | Mendoza | |||
Cadena: | Cadena1 | |||
Cantidad Impuestos | 1 | importe | 20 | |
Cadena: | Cadena2 | |||
Cantidad Impuestos | 1 | importe | 30 | |
Cant. Cadenas: | 2 | importe: | 50 | |
Cant. Prov.: | 3 | importe | 270 |
Veámoslo en código C++:
int main()
{
list
cargarLista(lista);
cout << "--- Realizando corte de control ---" << endl;
string provAnt;
string cadenaAnt;
int contCadena;
int contProv=0;
int total=0;
int totProv;
int impuestos;
list
while( it != lista.end() ) //Condición general. Fin de lista o EOF
{
provAnt = it->getProvincia();//Se carga la variable que guardará la clave anterior
//Se inicializa los contadores
contCadena = 0;
totProv=0;
while( it != lista.end() && provAnt == it->getProvincia() ) //Primer corte de control
{
cadenaAnt = it->getCadena();//var. que guardará la clave anterior
//inicializo contadores
total = 0;
impuestos = 0;
while ( it != lista.end() && provAnt == it->getProvincia() && cadenaAnt == it->getCadena() )//Segundo corte de control
{
total += it->getImporte();
impuestos++;
it++;//Se lee el siguiente
}
//Cambió la cadena
cout << "Cadena " << cadenaAnt << "- impuestos "<< impuestos << "- total: " << total << endl;
totProv += total;
contCadena++;
}
//Cambio la provincia
cout << "Prov - " << provAnt << "- cant cadenas "<< contCadena << "total prov "<< totProv << endl;
}
return 0;
}
Esta es la impresión del código al std out:
Buenos Aires - Cadena1 - i1 - $10
Buenos Aires - Cadena1 - i2 - $20
Buenos Aires - Cadena2 - i1 - $30
CABA - Cadena1 - i1 - $20
CABA - Cadena1 - i2 - $30
CABA - Cadena2 - i1 - $60
CABA - Cadena2 - i2 - $50
Mendoza - Cadena1 - i1 - $20
Mendoza - Cadena1 - i1 - $30
--- Realizando corte de control ---
Cadena Cadena1- impuestos 2- total: 30
Cadena Cadena2- impuestos 1- total: 30
Prov - Buenos Aires- cant cadenas 2total prov 60
Cadena Cadena1- impuestos 2- total: 50
Cadena Cadena2- impuestos 2- total: 110
Prov - CABA- cant cadenas 2total prov 160
Cadena Cadena1- impuestos 2- total: 50
Prov - Mendoza- cant cadenas 1total prov 50
gracias, me fue de ayuda.
ResponderEliminarsaludos