Saltar al contenido principal

Matrices y datos tabulares

Un array organiza una secuencia. Cuando los datos tienen filas y columnas —ventas por tienda y mes, notas por alumno y prueba— podemos usar un array bidimensional, al que llamaremos matriz.

Crear una matriz​

int[][] ventas = new int[3][4];

Esta matriz tiene tres filas y cuatro columnas. Los valores int comienzan en 0.

También podemos inicializarla con datos:

int[][] ventas = {
{10, 12, 9, 15},
{7, 11, 13, 8},
{14, 10, 12, 16}
};

Cada bloque interior representa una fila.

Acceder y modificar​

Necesitamos dos índices:

System.out.println(ventas[0][0]); // 10
System.out.println(ventas[2][3]); // 16

ventas[1][2] = 14;

El primer índice selecciona la fila y el segundo, la columna. Ambos empiezan en 0.

Práctica inmediata​

En una tabla de dos alumnos y tres notas, muestra la segunda nota del primer alumno y cambia la tercera del segundo:

int[][] notas = {
{7, 8, 6},
{5, 9, 7}
};

System.out.println(notas[0][1]); // 8
notas[1][2] = 10;

Longitud de filas y columnas​

System.out.println(ventas.length);       // filas: 3
System.out.println(ventas[0].length); // columnas de la fila 0: 4

matriz.length cuenta filas. matriz[fila].length cuenta los elementos de esa fila.

Recorrer con bucles anidados​

for (int fila = 0; fila < ventas.length; fila++) {
for (int columna = 0; columna < ventas[fila].length; columna++) {
System.out.print(ventas[fila][columna] + " ");
}
System.out.println();
}

Por cada fila, el bucle interior recorre todas sus columnas. Usar ventas[fila].length hace que el recorrido también sea seguro si las filas tienen longitudes diferentes.

Sumar por filas​

for (int fila = 0; fila < ventas.length; fila++) {
int sumaFila = 0;

for (int columna = 0; columna < ventas[fila].length; columna++) {
sumaFila += ventas[fila][columna];
}

System.out.println("Fila " + fila + ": " + sumaFila);
}

sumaFila se reinicia al comenzar cada fila. Si se declarara antes del bucle exterior, acumularía también las filas anteriores.

Sumar por columnas​

En una matriz rectangular podemos recorrer primero las columnas:

for (int columna = 0; columna < ventas[0].length; columna++) {
int sumaColumna = 0;

for (int fila = 0; fila < ventas.length; fila++) {
sumaColumna += ventas[fila][columna];
}

System.out.println("Columna " + columna + ": " + sumaColumna);
}

Este ejemplo presupone que hay al menos una fila y que todas tienen el mismo número de columnas.

Buscar un valor​

int buscado = 13;
int filaEncontrada = -1;
int columnaEncontrada = -1;

for (int fila = 0; fila < ventas.length; fila++) {
for (int columna = 0; columna < ventas[fila].length; columna++) {
if (ventas[fila][columna] == buscado) {
filaEncontrada = fila;
columnaEncontrada = columna;
}
}
}

System.out.println(filaEncontrada + ", " + columnaEncontrada);

Los dos índices describen una celda. En esta versión, si el valor se repite, conservamos la última coincidencia.

Programa completo: temperaturas semanales​

public class TemperaturasSemanales {
public static void main(String[] args) {
int[][] temperaturas = {
{18, 20, 21, 19},
{17, 22, 23, 20},
{16, 19, 20, 18}
};

mostrarTabla(temperaturas);
mostrarPromediosPorFila(temperaturas);
mostrarMaximo(temperaturas);
}

public static void mostrarTabla(int[][] datos) {
for (int fila = 0; fila < datos.length; fila++) {
for (int columna = 0; columna < datos[fila].length; columna++) {
System.out.print(datos[fila][columna] + " ");
}
System.out.println();
}
}

public static void mostrarPromediosPorFila(int[][] datos) {
for (int fila = 0; fila < datos.length; fila++) {
int suma = 0;
for (int valor : datos[fila]) {
suma += valor;
}
double promedio = (double) suma / datos[fila].length;
System.out.println("Promedio fila " + fila + ": " + promedio);
}
}

public static void mostrarMaximo(int[][] datos) {
int maximo = datos[0][0];
int mejorFila = 0;
int mejorColumna = 0;

for (int fila = 0; fila < datos.length; fila++) {
for (int columna = 0; columna < datos[fila].length; columna++) {
if (datos[fila][columna] > maximo) {
maximo = datos[fila][columna];
mejorFila = fila;
mejorColumna = columna;
}
}
}

System.out.println("Máxima: " + maximo + " en "
+ mejorFila + ", " + mejorColumna);
}
}

Dividimos presentación, promedios y búsqueda en métodos. Para simplificar, asumimos que la matriz y sus filas contienen datos.

Ampliación: filas irregulares​

Java permite que cada fila tenga una longitud distinta:

int[][] registros = {
{3, 5},
{8, 2, 9},
{4}
};

No necesitamos profundizar ahora. La regla importante es recorrer cada fila con registros[fila].length en lugar de asumir un tamaño común.

Errores habituales​

  • Intercambiar fila y columna al acceder.
  • Usar matriz.length como número de columnas.
  • Escribir <= en alguno de los recorridos.
  • Reiniciar un acumulador en el nivel incorrecto.
  • Suponer que todas las filas miden lo mismo sin haberlo garantizado.
  • Acceder a matriz[0] sin comprobar que existe alguna fila.

Ejercicio: ventas por tienda​

Una matriz contiene las ventas de dos tiendas durante tres meses:

Tienda 0: 12, 15, 10
Tienda 1: 9, 18, 14

Muestra el total de cada tienda, el total de cada mes y la celda con la venta máxima.

Resultados: tiendas 37 y 41; meses 21, 33 y 24; máxima 18 en fila 1, columna 1.

Solución razonada​

public class ResumenVentas {
public static void main(String[] args) {
int[][] ventas = {
{12, 15, 10},
{9, 18, 14}
};

for (int fila = 0; fila < ventas.length; fila++) {
int totalTienda = 0;
for (int columna = 0; columna < ventas[fila].length; columna++) {
totalTienda += ventas[fila][columna];
}
System.out.println("Tienda " + fila + ": " + totalTienda);
}

for (int columna = 0; columna < ventas[0].length; columna++) {
int totalMes = 0;
for (int fila = 0; fila < ventas.length; fila++) {
totalMes += ventas[fila][columna];
}
System.out.println("Mes " + columna + ": " + totalMes);
}

int maximo = ventas[0][0];
int filaMaximo = 0;
int columnaMaximo = 0;

for (int fila = 0; fila < ventas.length; fila++) {
for (int columna = 0; columna < ventas[fila].length; columna++) {
if (ventas[fila][columna] > maximo) {
maximo = ventas[fila][columna];
filaMaximo = fila;
columnaMaximo = columna;
}
}
}

System.out.println("Máxima: " + maximo + " en "
+ filaMaximo + ", " + columnaMaximo);
}
}

Cambiar el orden de los bucles nos permite agrupar por tienda o por mes. Ya contamos con todas las herramientas conceptuales de Java 1; ahora toca combinarlas en problemas completos.