Ir al contenido
Ayotl

← Estructuras de datos desde cero · Lección 4/32

Arreglos e índices

✕
1/7

Casillas en fila, desde el 0

Un arreglo guarda sus elementos uno junto a otro, en casillas numeradas. El número de la casilla es su índice, y se empieza a contar en 0: el primero es arr[0] y el último es arr[arr.length - 1].

Como las casillas van seguidas en la memoria, para llegar a la casilla 7 basta con hacer una cuenta: «donde empieza el arreglo + 7 casillas». No hay que pasar por las anteriores. Por eso leer o escribir arr[i] cuesta O(1), sin importar si el arreglo tiene diez elementos o diez millones.

125821301234arr[3] ↓
leccion.js

$ node leccion.js

Pulsa CORRER (o Ctrl+Enter).

Qué mirar

  • precios[3] es 21: el cuarto elemento, porque se cuenta desde 0.
  • El último se pide con length - 1, no con length.
  • Cambiar la casilla 1 no movió a nadie más.

Array en MDN ↗

Toda la lección en una página

Casillas en fila, desde el 0

Un arreglo guarda sus elementos uno junto a otro, en casillas numeradas. El número de la casilla es su índice, y se empieza a contar en 0: el primero es arr[0] y el último es arr[arr.length - 1].

Como las casillas van seguidas en la memoria, para llegar a la casilla 7 basta con hacer una cuenta: «donde empieza el arreglo + 7 casillas». No hay que pasar por las anteriores. Por eso leer o escribir arr[i] cuesta O(1), sin importar si el arreglo tiene diez elementos o diez millones.

125821301234arr[3] ↓
const precios = [12, 5, 8, 21, 3];

console.log(precios[0]);                  // el primero
console.log(precios[3]);                  // el cuarto
console.log(precios[precios.length - 1]); // el último

precios[1] = 6;                           // escribir también es O(1)
console.log(precios);
  • precios[3] es 21: el cuarto elemento, porque se cuenta desde 0.
  • El último se pide con length - 1, no con length.
  • Cambiar la casilla 1 no movió a nadie más.

Fuera del arreglo

¿Qué pasa si pides una casilla que no existe? En C o en Java eso es un error grave (o algo peor: leer basura de la memoria). JavaScript es más relajado y te devuelve undefined, sin avisar. Es cómodo, pero esconde errores: un índice que se pasó por uno da undefined y el programa sigue como si nada.

El error más común con arreglos tiene nombre: «por uno» (*off by one*). Un ciclo i <= arr.length da una vuelta de más y lee la casilla que no existe.

const dias = ["lun", "mar", "mié"];

console.log(dias[3]);   // no existe
console.log(dias[-1]);  // tampoco: no cuenta desde atrás
console.log(dias.at(-1)); // at() sí cuenta desde atrás

// El error «por uno»: <= da una vuelta de más
for (let i = 0; i <= dias.length; i++) {
  console.log(i, dias[i]);
}
  • dias[3] y dias[-1] dan undefined, sin error.
  • at(-1) es la forma moderna de pedir el último.
  • La última vuelta del ciclo imprime 3 undefined: ésa es la vuelta de más.

Rejillas: arreglos de arreglos

Un tablero, un mapa o una hoja de cálculo es un arreglo de filas, y cada fila es otro arreglo. Se lee con dos índices: primero la fila (y) y luego la columna (x): rejilla[y][x].

Así guarda Snake de Daily Challenge sus muros: un arreglo de 17 filas con 16 casillas cada una, true donde hay muro. Revisar si una casilla está libre es una lectura O(1).

  • x muro
const mapa = [
  "xxxxxx",
  "x....x",
  "x.xx.x",
  "x....x",
  "xxxxxx",
];
// Del texto a una rejilla de booleanos: true = muro
const muros = mapa.map(fila => [...fila].map(c => c === "x"));

console.log(muros.length, "filas,", muros[0].length, "columnas");
console.log(muros[2][2]);  // fila 2, columna 2
console.log(muros[1][2]);  // fila 1, columna 2
  • 5 filas de 6 columnas.
  • muros[2][2] es true: en la fila 2 hay muro en medio.
  • muros[1][2] es false: pasillo. El orden importa: fila primero, columna después.