1. ¿En qué se diferencian los arrays irregulares de los bidimensionales?
Ya hemos llegado al tema que muchos llaman «arrays de arrays» o «arrays irregulares» — en inglés jagged arrays. A diferencia de los arrays bidimensionales, los arrays irregulares te dejan guardar columnas de diferentes longitudes. Es como si tuvieras un complejo de edificios, donde cada edificio tiene su propio número de pisos — en uno hay 5 pisos, en otro 20, y en el tercero solo uno.
Un array irregular es un array donde cada elemento es a su vez un array. Y esos arrays internos (también llamados «subarrays») pueden tener longitudes diferentes.
La diferencia principal:
- En un array bidimensional cada «fila» (y cada «columna») tiene el mismo número de elementos. Ejemplo: int[,] grid = new int[3, 5]; — siempre tenemos 3 filas de 5 elementos.
- En un array irregular ¡cada fila puede tener una longitud diferente! Ejemplo: int[][] jagged = new int[3][]; — y luego inicializamos cada fila (subarray) como queramos.
Así se ve visualmente:
| Array bidimensional | Array irregular | |
|---|---|---|
| Número de elementos | Fijo (por ejemplo, 3x5) | Pueden variar entre filas |
| Indexación | |
|
| Flexibilidad | Baja | Alta |
| Uso | Tablas, matemáticas | Datos no uniformes: listas de estudiantes con diferente número de notas, triángulos |
Visualización: comparemos un array bidimensional y uno irregular
Array bidimensional (3x3):
┌───┬───┬───┐
│ 1 │ 2 │ 3 │
├───┼───┼───┤
│ 4 │ 5 │ 6 │
├───┼───┼───┤
│ 7 │ 8 │ 9 │
└───┴───┴───┘
Array irregular (longitudes diferentes):
┌───┬───┐
│ 1 │ 2 │
├───┼───┼───┬───┐
│ 3 │ 4 │ 5 │ 6 │
├───┼───┴───┴───┘
│ 7 │
└───┘
2. Sintaxis de declaración e inicialización de un array irregular
¡Declarar un array irregular no es más difícil que declarar los tipos anteriores! No te asustes por los dobles corchetes:
int[][] jaggedArray = new int[3][];
Esto significa que tenemos un array de 3 elementos, y cada uno de ellos es también un array de int. ¡Pero los arrays internos aún no existen! Para entenderlo mejor, vamos a verlo paso a paso.
Inicialización paso a paso de un array irregular
Paso 1 — crear el array principal (externo):
int[][] jaggedArray = new int[3][];
Ahora tenemos 3 «filas», pero todas son null por ahora.
Paso 2 — crear y rellenar los arrays internos (subarrays):
Por ejemplo, que la primera fila tenga longitud 2, la segunda 4 y la tercera 3:
jaggedArray[0] = new int[2]; // 2 elementos en la primera fila
jaggedArray[1] = new int[4]; // 4 elementos en la segunda fila
jaggedArray[2] = new int[3]; // 3 elementos en la tercera fila
Paso 3 — rellenar con valores:
¡Los arrays internos son arrays normales! Por ejemplo:
jaggedArray[0][0] = 1;
jaggedArray[0][1] = 2;
jaggedArray[1][0] = 3;
jaggedArray[1][1] = 4;
jaggedArray[1][2] = 5;
jaggedArray[1][3] = 6;
jaggedArray[2][0] = 7;
jaggedArray[2][1] = 8;
jaggedArray[2][2] = 9;
Inicialización rápida de un array irregular
Puedes crear y rellenar el array irregular de una vez si ya sabes los valores:
int[][] jaggedArray = new int[][]
{
new int[] { 1, 2 },
new int[] { 3, 4, 5, 6 },
new int[] { 7, 8, 9 }
};
O un poco más corto, omitiendo el tipo de los arrays internos:
int[][] jaggedArray = {
new[] { 1, 2 },
new[] { 3, 4, 5, 6 },
new[] { 7, 8, 9 }
};
3. Recorrer y trabajar con arrays irregulares
Recorrer un array irregular no es más difícil que uno bidimensional, pero ahora el bucle externo va por las filas y el interno por los elementos de la fila (que pueden tener longitudes diferentes):
for (int i = 0; i < jaggedArray.Length; i++)
{
Console.WriteLine($"Fila {i}:");
for (int j = 0; j < jaggedArray[i].Length; j++)
{
Console.Write($"{jaggedArray[i][j]} ");
}
Console.WriteLine();
}
Resultado en pantalla:
Fila 0:
1 2
Fila 1:
3 4 5 6
Fila 2:
7 8 9
Puedes usar foreach para no preocuparte por los índices:
foreach (int[] row in jaggedArray)
{
foreach (int value in row)
{
Console.Write($"{value} ");
}
Console.WriteLine();
}
4. Cómo funciona un array de arrays
Ahora vas a ver cómo funcionan realmente los arrays de arrays. ¿Listo?
Si con un array normal «la variable-array guarda una referencia al contenedor que guarda los elementos del array». En el caso de los arrays irregulares la cosa es un poco más explosiva: la variable-array-de-arrays guarda una referencia a un contenedor que guarda referencias a arrays unidimensionales. Mejor verlo una vez que explicarlo cien veces:
A la izquierda tenemos la «variable-array-de-arrays», que guarda una referencia al «objeto-contenedor de arrays». En el centro está el «objeto-contenedor de arrays», en cuyas celdas se guardan referencias a arrays unidimensionales — las filas del array irregular. Y a la derecha ves cuatro arrays unidimensionales — las filas de nuestro array irregular.
Así es como realmente funcionan los arrays irregulares. Y este enfoque le da al programador de C# varias ventajas:
Primero, como el «contenedor de contenedores» guarda referencias a «arrays-fila», podemos cambiar filas muy rápido y fácil. Para acceder al «contenedor de contenedores», solo tienes que poner un índice en vez de dos. Ejemplo:int[][] data = new int[2][];
data[0] = new int[5]; // primera fila — array de 5 elementos
data[1] = new int[5]; // segunda fila — array de 5 elementos
int[] row1 = data[0];
int[] row2 = data[1];
Con este código puedes intercambiar filas:
// Matriz importante con datos
int[][] matrix = {
new int[] {1, 2, 3, 4, 5},
new int[] {5, 4, 3, 2, 1}
};
int[] tmp = matrix[0];
matrix[0] = matrix[1];
matrix[1] = tmp;
Si accedes a una celda de un array bidimensional pero solo pones un índice después del nombre del array, así accedes al contenedor de contenedores, donde se guardan referencias a arrays unidimensionales normales.
5. Escenarios típicos de uso de arrays irregulares
¿Cuándo puede ser más útil un array irregular que uno bidimensional?
- Si guardas para cada usuario una cantidad diferente de algún dato: notas por asignatura, compras, comentarios, etc.
- Si tus datos tienen una estructura triangular o escalonada (por ejemplo, para mostrar pirámides, triángulos de Pascal, etc.).
- Si quieres ahorrar memoria: en un array bidimensional todas las filas son fijas, pero en uno irregular solo tienes los elementos que necesitas.
Ejemplo de la vida real: gestor de notas de estudiantes
¡Vamos a ampliar nuestro proyecto de clase! Supón que cada estudiante puede tener diferente número de notas por cada asignatura. Por ejemplo, unos entregan más trabajos, otros menos. Para esto, un array irregular es perfecto.
Supón que tenemos tres estudiantes, y estas son sus notas en diferentes tareas de matemáticas:
| Estudiante | Notas |
|---|---|
| 0 | 5, 4 |
| 1 | 3, 4, 4 |
| 2 | 5 |
Declaramos el array así:
int[][] studentMarks = new int[3][];
studentMarks[0] = new int[] { 5, 4 }; // Primer estudiante - 2 notas
studentMarks[1] = new int[] { 3, 4, 4 }; // Segundo estudiante - 3 notas
studentMarks[2] = new int[] { 5 }; // Tercer estudiante - 1 nota
Mostramos las notas de cada estudiante:
for (int i = 0; i < studentMarks.Length; i++)
{
Console.Write($"Estudiante {i}: ");
for (int j = 0; j < studentMarks[i].Length; j++)
{
Console.Write(studentMarks[i][j] + " ");
}
Console.WriteLine();
}
Usar arrays irregulares con otros tipos
Un array irregular puede ser de lo que sea: strings, arrays de otros arrays (¡más profundo!), incluso tus propios objetos.
Ejemplo: array de strings
string[][] groups = new string[][]
{
new string[] { "Ivan", "Pyotr" },
new string[] { "Maria", "Aleksei", "Sergey" },
new string[] { "Vasilisa" }
};
6. Particularidades y errores comunes
Los arrays irregulares son muy flexibles, pero hay trampas por todas partes.
- Si no inicializaste alguno de los arrays internos (jaggedArray[1] = ...), intentar acceder a él te dará un NullReferenceException. ¡No olvides inicializar cada array interno!
- No todas las filas (subarrays) tienen la misma longitud. Si usas un índice fijo en la segunda dimensión, puedes salirte del array.
- ¡No los confundas con arrays bidimensionales! La indexación es así: array[i][j], no array[i, j].
GO TO FULL VERSION