---
title: "Arreglos: Fundamentos"
---

Los arreglos (*arrays*) son una manera sistematizada de almacenar múltiples variables del mismo tipo. 

En combinación con ciclos `while` o `for`, nos permiten programar rutinas que actúan sobre  diversos valores a la vez.

[[Ciclos while y for]](/notas/ciclos.html)

# Planteamiento del problema

## Una variable

Partimos de este ejemplo de código de animación básica con acumuladores, en el que un punto se mueve hacia la derecha y al llegar al borde vuelve a empezar su camino en la izquierda.

[[Animación básica con acumuladores]](/notas/animacion-basica.html)

```java
// 1) variable para almacenar la posición horizontal del punto
float px; 

void setup(){
  size(400, 400);
  strokeWeight(10);
  stroke(255);

  px = 0; // 2) valor inicial de posición
}

void draw(){
 background(0);
 // 3) dibuja el punto con pos. horizontal: px
 // y posición vertical: 200
 point(px, 200);
 
 // 4) incrementa la posición horizontal
 px = px + 2;
 // 5) y si llega al borde derecho, reinicia
 if(px > width){
  px = 0; 
 }
}
```

## Múltiples variables, sin arreglos

Supongamos que queremos tener más puntos moviéndose de la misma manera, pero empezando en diferentes posiciones.

Previo a utilizar arreglos, lo que haríamos sería crear una variable por cada punto y repetir por cada una los 5 pasos del ejemplo previo.

Un ejemplo con tres puntos se vería así:

```java
// 1) variables para almacenar las posiciones horizontales de los puntos
float px1, px2, px3; 

void setup(){
  size(400, 400);
  strokeWeight(10);
  stroke(255);

// 2) valor inicial de posición
  px1 = 0; 
  px2 = 50; 
  px3 = 200; 
}

void draw(){
 background(0);
 // 3) dibuja los puntos con pos. horizontal: px
 // y posición vertical: 200
 point(px1, 200);
 point(px2, 200);
 point(px3, 200);
 
 // 4) incrementa las posiciones horizontales
 px1 = px1 + 2;
 px2 = px2 + 2;
 px3 = px3 + 2;

 // 5) y si alguna llega al borde derecho, reinicia
 if(px1 > width){
  px1 = 0; 
 }
 if(px2 > width){
  px2 = 0; 
 }
 if(px3 > width){
  px3 = 0; 
 }
}
```

Tal vez con tres puntos todavía es manejable, pero imagina cómo se vería el código con 5, 10, o 100 puntos.

Los arreglos nos permitirán tener un código con una extensión al primero, aunque tengamos miles de puntos.

## Con arreglos

El mismo programa, con arreglos, podría quedar de la siguiente forma:

```java
// 1) arreglo para almacenar las posiciones horizontales de los puntos
float[] px;

void setup(){
  size(400, 400);
  strokeWeight(10);
  stroke(255);

// 2) crea e inicializa arreglo con 3 puntos:
  px = new float[3];
  px[0] = 0; 
  px[1] = 50; 
  px[2] = 200; 
}

void draw(){
  background(0);

  // por cada elemento del arreglo...
  for (int i=0; i<px.length; i++) {
    // 3) dibuja los puntos con pos. horizontal: px[i]
    // y posición vertical: 200
    point(px[i], 200);

    // 4) incrementa la posición horizontal
    px[i] = px[i] + 2;

    // 5) y si alguna llega al borde derecho, reinicia
    if (px[i] > width) {
      px[i] = 0;
    }
  }
}
```

# Notación

Los símbolos que nos van a indicar que estamos usando arreglos son los corchetes `[ ]`.

## Declaración

Declaramos un arreglo con su tipo de dato y los corchetes:

```java
float[] posiciones; // declara arreglo
```

## Creación

A diferencia de otras variables básicas, antes de poder usar un arreglo necesitamos crearlo.

Al crearlo, indicamos el número de elementos que contendrá:

```java
posiciones = new float[100]; // crea arreglo de 100 elementos
```
## Atributo `.length`

Los arreglos tienen un atributo `.length` que nos indica el número de elementos que contiene.

```java
println( posiciones.length ); // imprime tamaño del arreglo
```

## Asignación y lectura

Cada elemento del arreglo tiene un **índice** numérico con el cual lo podemos ubicar. Podemos visualizarlo también como una *dirección*.

Los elementos están numerados a partir de 0, y llegan hasta `.length - 1`.

Por ejemplo, un arreglo de 5 elementos tendrá los índices 0, 1, 2, 3, 4.

Accederemos a cada índice con los corchetes `[ ]`:

```java
posiciones[0] = 200; // asigna 200 a la primera posición del arreglo
posiciones[1] = 10; // asigna 10 a la segunda posición del arreglo
```

Esa notación la podemos utilizar en lugar de cualquier variable.

Por ejemplo, aquí la tercera posición del arreglo se comporta como acumulador, leyendo el valor del elemento, sumándole 5, y guardando el resultado en la misma posición:

```java
posiciones[2] = posiciones[2] + 5;
```

Cuando queremos utilizar un índice fuera del rango del arreglo, recibiremos un error `ArrayIndexOutOfBoundsException`.

## Ciclos `for`

Una de las principales ventajas de los arreglos es que como podemos acceder a sus elementos a través de un valor numérico (el *índice*), podemos hacer que ese sea una variable que se incrementa de uno en uno (un *contador*).

La notación más utilizada es con una variable de tipo `int` llamada `i` que funciona como índice, y que recorre cada posición del arreglo con un ciclo `for` de la siguiente forma:

```java
for( int i=0; i<posiciones.length; i++){
  // realiza acciones con posiciones[i]
}
```

Lo que escribiremos dentro del ciclo `for` requiere un trabajo previo de identificar qué acciones son las que tomamos por cada elemento del arreglo, qué tienen en común, para entonces abstraerlas en términos de `i`.

### Inicializaciones

Este ejemplo inicializa todos los valores del arreglo en 0:

```java
for( int i=0; i<posiciones.length; i++){
  posiciones[i] = 0;
}
```

Y este asigna un valor aleatorio distinto a cada elemento:

```java
for( int i=0; i<posiciones.length; i++){
  posiciones[i] = random(width);
}
```

Aquí le asignamos un valor dado por un acumulador:

```java
float x = 0;
for( int i=0; i<posiciones.length; i++){
  posiciones[i] = x;
  x = x + 10;
}
```

### Lectura

Este ejemplo dibuja tantos puntos como elementos del arreglo, usando el valor leído como posición horizontal:

```java
for( int i=0; i<posiciones.length; i++){
  point( posiciones[i], 200 );
}
```

### Incrementos, condicionales

Este ciclo fue extraído del ejemplo de arriba. Aquí cada elemento del arreglo se incrementa y cuando supera un límite es reiniciado a 0

```java
for( int i=0; i<posiciones.length; i++){
  posiciones[i] = posiciones[i] + 10;
  if( posiciones[i] > width ){
    posiciones[i] = 0;
  }
}
```

# Multiplicidades

Podemos crear tantos arreglos como queramos. Si todos tienen el mismo tamaño, los podemos utilizar para referirse a diferentes características de una misma entidad.

Por ejemplo, los puntos del ejemplo de arriba pueden tener diferente posición vertical además de diferente posición horizontal. Este *sketch* inicializa 100 de ellos con posición aleatoria y los mueve en la misma dirección, reiniciándolos al llegar al final:

```java
// 1) arreglos para almacenar posiciones x,y de los puntos
float[] px;
float[] py;


void setup() {
  size(400, 400);
  strokeWeight(10);
  stroke(255);

  // 2) crea e inicializa arreglos con 100 elementos:
  px = new float[100];
  py = new float[100];

  for (int i=0; i<px.length; i++) {
    px[i] = random(width);
    py[i] = random(height);
  }
}

void draw() {
  background(0);

  // por cada elemento del arreglo...
  for (int i=0; i<px.length; i++) {
    // 3) dibuja los puntos con pos. horizontal: px[i]
    // y posición vertical py[i]
    point(px[i], py[i]);

    // 4) incrementa la posición horizontal
    px[i] = px[i] + 2;

    // 5) y si alguna llega al borde derecho, reinicia
    if (px[i] > width) {
      px[i] = 0;
    }

  }// cierra ciclo for
  
}

```

¿Cómo harías que los puntos se muevan en el eje vertical en vez del horizontal?

¿Cómo harías que al llegar al borde derecho, los puntos cambien su posición vertical a una nueva posición aleatoria? 

¿Cómo harías que cada punto tuviera una velocidad distinta?
