Salta el contingut

Arrays

Declaració i ús d'arrays

  • Un array és un conjunt indexat d'elements
  • Un array permet emmagatzemar diversos valors utilitzant una sola variable per a tot el conjunt
  • L'índex d'un array només pot ser un valor numèric
  • El primer element d'un array té l'índex 0
  • Els valors no han de ser forçosament consecutius, podem deixar posicions buides
  • Un sol array pot contenir elements de tipus diferents, i fins i tot pot contenir altres arrays

Declaració amb Array

const fruites = new Array();
fruites[0] = "taronja";
fruites[1] = "llimona";
fruites[2] = "plàtan";

o bé

const fruites = new Array( "taronja", "llimona", "plàtan" );

Posar el new és opcional

En el cas específic dels Arrays, la utilització de new davant d'Array() és opcional:

const array1 = new Array()
const array2 = Array()

Cas especial en utilitzar new

Si inicialitzem l'array amb un sol valor numèric, es crea un array de la longitud donada i amb cada posició buida:

const fruites = new Array( 40 ); // fruites.length == 40

Declaració amb [ ]

const fruites = [];
fruites[0] = "taronja";
fruites[1] = "llimona";
// Deixem les posicions 2 i 3 buides
fruites[4] = "plàtan";

o bé

const fruites = [ "taronja", "llimona", , , "plàtan" ];

Recomanació

A nivell de rendiment del codi, és més eficient declarar els arrays amb [ ] que no pas amb new Array.
També és el que porta menys confusió al codi.

Per tant, el mètode recomanat és fer servir sempre [ ]

Per accedir a un element individual d'un array, utilitzem el seu índex:

fruites[0]; // Primer element de l'array

Recorregut d'arrays

Si considerem el següent array:

const fruites = [ "taronja", "llimona", , , "plàtan" ];

El podem recòrrer de diferents formes:

Iteració for

Recorrem consecutivament els índexs de l'array i en llegim el seu valor, tenint en compte que el primer índex és 0.
Si una posició no té un valor assignat, retornarà undefined.

for (let i = 0; i < fruites.length; i++)
{
    llista += `<li>${ fruites[ i ] }`;
}

Iteració for..in

Recorrem tots els índexs de l'array, sense necessitat de saber el seu valor numèric.
Només retorna aquells índex on hi ha algun valor assignat.

for (clau in fruites)
{
    llista += `<li>índex ${ clau } = ${ fruites[ clau ] }`;
}

Atenció

for..in no garanteix retornar les claus d'un array en ordre, per tant no es recomana fer-lo servir per iterar arrays.
És més adequat per recòrrer objectes, tot i que funciona sobre qualsevol tipus enumerable.

Iteració for..of

Recorrem tots els valors de l'array, sense necessitat de conèixer les seves claus.
Retorna els valors existents fins a la longitud de l'array, encara que no estiguin assignats.

for (valor of fruites)
{
    llista += `<li>${ valor }`;
}

Consell

for..of és el mètode més recomanat per recòrrer arrays i strings.
En canvi, no es pot utilitzar amb objectes.

Explicació de les diferències entre for, for..in i for..of

for..in versus for..of Loops

Iteració forEach

Recorrem les parelles de valors i claus (índexs) de l'array.
A diferència dels anteriors, forEach és un mètode dels arrays i rep com a paràmetre una funció:

fruites.forEach( function(valor, clau) {
    llista += `<li>índex ${clau} = ${valor}`;
} )

Propietats i mètodes

Un dels avantatges principals a l'hora de fer servir arrays és poder utilitzar els seus mètodes predefinits, ja que poden realitzar moltes funcions que ens estalviaran codi.

Algunes propietats i mètodes dels arrays:

length

Propietat que retorna el nombre d'elements (assignats o no) d'un array, que es correspon amb el nombre següent del seu índex més gran.

var fruites = [ "taronja", "llimona", "plàtan" ];     // fruites.length = 3
var fruites = [ "taronja", "llimona", , , "plàtan" ]; // fruites.length = 5

Si li assignem un valor, truncarà o expandirà (afegint elements buits) l'array a la longitud donada.

fruites.length = 1;  // fruites = [ "taronja" ]
fruites.length = 0;  // fruites = [ ]
fruites = [];        // Equivalent a l'anterior

concat()

Uneix dos o més arrays en un de sol, o afegeix valors al final d'un array.
Retorna un array nou, no modifica l'array original.

Paràmetres
Arrays a concatenar, separats per comes

const fruites    = [ "taronja", "llimona", "plàtan" ];
const mesFruites = [ "pera", "kiwi" ];

let resultat1  = fruites.concat( mesFruites );          // variable
let resultat2  = fruites.concat( [ "pera", "kiwi" ] );  // array
let resultat3  = fruites.concat( "pera", "kiwi" );      // valors individuals

slice()

Extreu una part determinada d'un array.
Retorna un array nou, no modifica l'array original.

Paràmetres
Inici: valor a partir del que es comencen a extreure dades (per defecte la posició 0)
Final: valor on s'atura l'extracció de dades, però sense incloure'l (per defecte la longitud de l'array)

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
let resultat = fruites.slice(1,3);

Còpia d'arrays

És important que els valors per defecte de slice seleccionin tot el contingut de l'array.
Això fa que amb aquests instrucció es pugui fer una còpia dels valors d'un array.

Per defecte, si assignem un array existent a una nova variable les dues estaran apuntant al mateix array:

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ]

let fruites2 = fruites

fruites.push("coco")

// fruites =  ['taronja', 'llimona', 'plàtan', 'pera', 'kiwi', 'coco']
// fruites2 = ['taronja', 'llimona', 'plàtan', 'pera', 'kiwi', 'coco']

En canvi si utilitzem slice es copien els valors ja que retorna un nou array:

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ]

let fruites2 = fruites.slice()

fruites.push("coco")

// fruites =  ['taronja', 'llimona', 'plàtan', 'pera', 'kiwi', 'coco']
// fruites2 = ['taronja', 'llimona', 'plàtan', 'pera', 'kiwi']

També es pot aconseguir el mateix resultat amb l'operador spread:

let fruites2 = [...fruites] // És equivalent a fruites2 = fruites.slice()

Important

Això només s'aplica als valors de tipus primitius: cadenes, numèrics i booleans.
Els arrays i objectes continguts dins de l'array es copien per referència.

indexOf()

Retorna la posició de la primera coincidència un element donat dins d'un array.
La cerca distingeix majúscules i minúscules.
Si l'element no es troba dins l'array, retorna -1.

Paràmetres
Cadena que conté l'element a cercar
Índex a partir del qual començar la cerca (opcional)

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
let resultat = fruites.indexOf("pera");

lastIndexOf()

Retorna la posició de la darrera coincidència un element donat dins d'un array.
La cerca distingeix majúscules i minúscules.
Si l'element no es troba dins l'array, retorna -1.

Paràmetres
Cadena que conté l'element a cercar
Índex a partir del qual començar la cerca (opcional)

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
let resultat = fruites.lastIndexOf("pera");

includes()

Retorna un booleà indicant si un element donat es troba dins d'un array.
La cerca distingeix majúscules i minúscules.

Paràmetres
Cadena que conté l'element a cercar
Índex a partir del qual començar la cerca (opcional)

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
let resultat = fruites.includes("llimona");

push()

Afegeix nous elements al final de l'array.
Retorna la nova mida de l'array.

Paràmetres
Valors a afegir separats per coma

const fruites  = [ "taronja", "llimona", "plàtan" ];
let resultat = fruites.push( "pera", "kiwi" ); // resultat = 5

Utilitat

Juntament amb pop() són mètodes per operar amb un array com una pila.

pop()

Retorna el darrer element de l'array i l'elimina, modificant la longitud de l'array.
Si l'array és buit, retona undefined.
No espera cap paràmetre.

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
let resultat = fruites.pop(); // resultat = "kiwi"

Utilitat

Juntament amb push() són mètodes per operar amb un array com una pila.

shift()

Retorna el primer element de l'array (posició 0) i l'elimina, desplaçant la resta d'elements.
Si l'array és buit, retona undefined.
No espera cap paràmetre.

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
let resultat = fruites.shift(); // resultat = "taronja"

Ús pràctic

Combinant push() i shift(), podem fer que un array actui com una cua.
Les cues són molt útils per crear buffers de dades.

Utilitat

Juntament amb unshift() són mètodes per operar amb un array com una pila inversa.

unshift()

Afegeix nous elements a l'inici de l'array (posició 0) desplaçant la resta d'elements.
Retorna la nova mida de l'array.

const fruites  = [ "taronja", "llimona", "plàtan" ];
let resultat = fruites.unshift( "pera", "kiwi" ); // resultat = 5

Utilitat

Juntament amb shift() són mètodes per operar amb un array com una pila inversa.

join()

Retorna una cadena amb tots els elements de l'array units per una cadena separadora, que per defecte és una coma.
No modifica l'array original.

Paràmetres
Cadena separadora, si s'omet és una coma ","

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
let resultat = fruites.join(";");

sort()

Ordena alfabèticament els elements d'un array.
Aquest mètode modifica l'array original.

Paràmetres
Opcionalment, una funció d'ordenació diferent de la per defecte

const fruites = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
fruites.sort();

toSorted()

El mètode toSorted() fa la mateixa funció que sort() retornant un nou array i sense modificar l'original.

reverse()

Inverteix l'ordre de tots els elements d'un array (reversat).
Aquest mètode modifica l'array original.
No espera cap paràmetre.

const fruites = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
fruites.reverse();

toReversed()

El mètode toReversed() fa la mateixa funció que reverse() retornant un nou array i sense modificar l'original.

splice()

Afegeix o elimina elements a una posició donada de l'array.
Aquest mètode modifica l'array original.
Retorna un array amb els elements eliminats.

Paràmetres
Inici: índex de la posició on es faran els canvis a l'array
Esborrats: número d'elements a eliminar a partir de l'inici indicat
Nous elements: elements a afegir a l'array a partir del punt d'inici

Segons els paràmetres que utilitzem, es farà una inserció, un esborrat o les dues coses alhora.

const fruites = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
fruites.splice(1, 2, "mandarina");

toSpliced()

El mètode toSpliced() fa la mateixa funció que splice() retornant un nou array i sense modificar l'original.

fill()

Canvia els elements d'un array per altre valor entre dues posicions donades.
Aquest mètode modifica l'array original.
Retorna l'array modificat.

Paràmetres
Valor: element amb el que s'ompliran les posicions de l'array
Inici: índex de la primera posició a omplir (per defecte 0)
Final: índex de la última posició a omplir, però sense incloure-la (per defecte array.length)

const fruites = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
fruites.fill("mandarina", 1, 3);

find()

Retorna el primer element de l'array que satisfà (fa retornar true) la funció de cerca passada com a paràmetre.
Si cap valor de l'array satisfà la funció de cerca, retorna undefined.

Paràmetres
Aquest mètode rep una funció com a paràmetre.

const fruites = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];

// Funció anònima com a paràmetre
// "e" iterarà per cada element de l'array o fins que un retorni true
fruites.find( function(e) { return e.length == 4 } )

// És molt més convenient utilitzar les funcions fletxa
fruites.find( e => e.length == 4 );

Consells

Si el que ens interessa és l'índex de l'element trobat enlloc del seu valor, podem utilitzar el mètode findIndex().
Si només volem saber si algun element satisfà la funció de cerca, podem utilitzar el mètode some() que retorna un booleà.

filter()

Retorna un nou array amb els elements de l'array que satisfan (fa retornen true) la funció de cerca passada com a paràmetre.
Si cap valor de l'array satisfà la funció de cerca, retorna un array buit.

Paràmetres
Aquest mètode rep una funció com a paràmetre.

const fruites = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
fruites.filter( e => e.length == 4 );

map()

Retorna un nou array on cada element correspon al resultat d'executar la funció passada com a paràmetre sobre cada element de l'array original.

Paràmetres
Aquest mètode rep una funció com a paràmetre.

const fruites = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
fruites.map( e => e.length );

reduce()

Redueix un array a un sol valor a través d'una funció reductora que s'executa per cada element de l'array original.

Paràmetres
Aquest mètode rep com a paràmetres una funció i un valor inicial per l'acumulador.
Ha de seguir la següent sintaxi:

( ( acumulador, valorElement ) => càlcul() , valorInicial )

Exemple
Sumar la longitud de totes les cadenes d'un array

const fruites = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
fruites.reduce( ( ac, e ) => ac += e.length, 0 );

Paràmetres addicionals

La funció passada als mètodes find(), filter(), map() i reduce() pot tenir també aquests paràmetres:

  • element: l'element de l'array que s'està processant
  • índex: l'índex de l'element que s'està processant
  • array: l'array sobre el que s'està fent el procés

També es pot passar com a paràmetre un valor alternatiu per this dins de la funció.

Exemples

Taulell dibuixat en funció dels valors d'un array (monocrom)

Taulell dibuixat en funció dels valors d'un array (color)

Arrays multidimensionals

A JavaScript no hi ha una sintaxi específica per crear arrays de més d'una dimensió.
Hem de crear un array principal i a cadascuna de les seves posicions crear-hi un nou array, i així successivament fins arribar a la dimensió desitjada.

Declaració d'un array multidimensional

Com amb els arrays simples, ho podem fer amb new:

// Declarem individualment cada array intern
const fila1 = new Array( "1", "2" );
const fila2 = new Array( "3", "4" );
const fila3 = new Array( "5", "6" );

// Finalment, l'array únic per contenir-los a tots
const taula = new Array( fila1, fila2, fila3 );

O bé amb la notació compacta utilitzant [ ]

const taula = [ ["1", "2"], ["3", "4"], ["5", "6"] ];

Un cop declarat l'array, podem accedir als elements individuals utilitzant un índex compost.

element valor
taula[ 0 ][ 0 ] 1
taula[ 2 ][ 1 ] 6
taula[ 2 ][ 3 ] undefined
taula[ 3 ][ 2 ] error

Exemple
Inicialitzar una taula de X * Y cel·les amb un array

const taula = [];

for ( let i = 0; i < X; i++ )
{
   taula[ i ] = [];

   for ( let j = 0; j < Y; j++ )
   {
      taula[ i ][ j ] = valor;
   }
}

Extensió d'arrays amb prototipus

Els prototipus en JavaScript ens permeten modificar el comportament de tipus bàsics afegint-los propietats i mètodes com si fossin objectes definits per nosaltres.
Amb això els podem afegir funcionalits addicionals sense haver de crear classes noves.

Podem afegir propietats i mètodes a l'objecte Array amb el constructor prototype.

Important!

Quan creem propietats i mètodes, tots els arrays del nostre codi els tindran, ja que modifiquem directament l'objecte Array i no un sol array individual.

Crear una propietat

Array.prototype.nova_propietat = valor;

Exemple

Array.prototype.idioma = "català";

const fruites  = [ "taronja", "llimona", "plàtan", "pera", "kiwi" ];
fruites.idioma; // "català"

const fruits  = [ "orange", "lemon", "banana", "pear", "kiwi" ];
fruits.idioma; // "català"
fruits.idioma = "english";

Crear un mètode

Array.prototype.nova_funcio = nom_de_funcio_existent;
Array.prototype.nova_funcio = function() { ... };

Exemple

Array.prototype.llistar = function () {
    document.write("Llistat en " + this.idioma);

    for (element of this)
        document.write(`<li>${element}`);
}

const fruites = ["taronja", "llimona", "plàtan", "pera", "kiwi"];

fruites.llistar()