This article also exists in: English

In ambito frontend, in particolar modo lavorando a stretto contatto con JS, capita il più delle volte di utilizzare Array per immagazzinare dati.

const _var = ['🤖','👽','☠️','🎅','🐨','🐧','💀'];

E molto spesso è necessario cercare elementi all’interno di questo set di dati: potrebbe servire trovare l’indice dell’elemento, o semplicemente sapere se l’elemento è presente… oppure ottenere un subset di elementi che rispettano un certo criterio.

Con l’avvento di ES6, sono stati introdotti molti metodi per le ricerche sugli Array.

Metodi utili ricerca su array

MetodoUtilitàRitorno
.includesRitorna true/false se il valore cercato esiste nell’arraybool
.findRitorna il primo elemento dell’array che soddisfa il criterio di ricerca oppure undefined se non trovatoobject|undefined
.filterRitorna un nuovo array contenente gli elementi dal set originario che soddisfano il criterio di ricercaArray
.indexOfRitorna il primo indice dell’elemento nel set se esiste, altrimenti ritorna -1Number

Quindi

  • Devo trovare se un elemento è presente in un array: posso usare .includes() direttamente, oppure verificare che .find() sia diverso da undefined, oppure verificare che .indexOf() sia diverso da -1
  • Devo trovare l’indice preciso di dove è presente l’elemento: indubbiamente la .indexOf() è il miglior metodo
  • Mi serve esattamente l’elemento che rispetta dei criteri all’interno dell’array: .find() o .filter() in caso di più valori (subset)

L’elemento è presente nell’array?

const people = ['🤖','👽','☠️','🎅','🐨','🐧','💀'];

//using includes
let isKoalaPresent = people.includes('🐨'); 
//using find
let isAlienPresent = typeof (people.find((el) => el === '👽')) !== 'undefined'; 
//using indexOf
let isRobotPresent = people.indexOf('🤖') !== -1;

Una necessità ad esempio potrebbe essere l’aggiungere, nel nostro set di dati, un Clown dopo Babbo Natale. Banalmente dovremmo trovare la posizione di Babbo Natale e posizionare successivamente il Clown.

Indice di un elemento nel set di dati

let people = ['🤖','👽','☠️','🎅','🐨','🐧','💀'];

let santaClausPosition = people.indexOf('🎅'); //3

// splice: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice?retiredLocale=it
// position of 🤡 is after 🎅, so ++santaClausPosition
people.splice(++santaClausPosition, 0, '🤡');

console.log(people);
//['🤖','👽','☠️','🎅','🤡','🐨','🐧','💀']
tldr

Anche se sia santaClausPosition++ che ++santaClausPosition incrementano la variabile a cui sono applicati, il risultato restituito da santaClausPosition++ è il valore della variabile prima dell’incremento, mentre il risultato restituito da ++santaClausPosition è il valore della variabile dopo che l’incremento è stato applicato.

tips

.indexOf può restituire l’indice dell’elemento in un array anche a partire da una certa posizione: in questo caso basta passare un intero come secondo parametro del metodo.
Inoltre, se si vuole iniziare la ricerca non dall’inizio ma dalla fine, esiste il metodo .lastIndexOf

let people = ['🤖','👽','☠️','🎅','🐨','🐧','🎅','💀'];

let santaClausPosition = people.indexOf('🎅', 4); //6

Elementi da array

Supponiamo di avere un set di dati che rappresenta delle stanze con degli individui all’interno.

let environment = [
    {
        name: 'Space Room',
        people: ['👽','🤖','👾'],
        type: 'ROBOT_ALIEN',
    },
    {
        name: 'Animal Court',
        people: ['🐨','🐧'],
        type: 'ANIMAL',
    },
    {
        name: 'Attention Field',
        people: ['💀','☠️','👾'],
        type: 'SKULL',
    },
    {
        name: 'Magic Room',
        people: ['🎅','🤡'],
        type: 'MAGIC',
    }
];

Vorrei trovare la stanza relativa agli animali.

let animalsRoom = environment.find((room) => room.type === 'ANIMAL');
console.log(animalsRoom);

/*
{
    name: 'Animal Court',
    people: ['🐨','🐧'],
    type: 'ANIMAL'
 }
*/

// NB: `(room) => room.type === 'ANIMAL'` è il criterio di ricerca. 
// Qualora il criterio relativo a room, torni true allora room 
// è un elemento accettato dal find.

Magari invece vorrei proprio la stanza dove è presente l’Alieno…

let alienRoom = environment.find((room) => room.people.includes('👽'));
console.log(alienRoom);
/*
{
	name: 'Space Room',
	people: ['👽','🤖','👾'],
	type: 'ROBOT_ALIEN'
}
*/

Nel caso invece di voler ottenere un sottoinsieme di dati potremmo usare .filter(). Per approfondire puoi anche vederlo in azione qui.

In realtà anche se è stato sviscerato in un precedente articolo, vorrei farvelo vedere in azione combinandolo con il concat(), per ottenere un array flatten da più sorgenti di dati. Ad esempio vorrei ottenere tutti i robot eventualmente presenti nelle varie stanze.

let filterRobot = (el) => el.includes('🤖') || el.includes('👾');

let robotPeoples = environment.filter((room) => filterRobot(room.people))
							  .map((el) => el.people.filter((entity) => filterRobot(entity)));
let robots = [].concat.apply([], robotPeoples);

console.log(robots);
//['🤖', '👾', '👾']

In questo articolo abbiamo visto, anche tramite qualche esempio pratico, un basilare approccio alla ricerca di elementi negli array in Javascript ES6+.

Combinando Array.filter(), Array.find(), Array.includes(), Array.indexOf() con .map() e .reduce() abbiamo un set di strumenti potentissimo per la manipolazione dei dati su Array.

About the author

For the last 15 years, Stefano Frasca has worked with a variety of web technologies both backend and frontend. He is currently focused on front-end development. On his day to day job, he is working as a FullStack developer & Frontend dev fan at Immobiliare Labs IT. He has worked remotely for years, passionate about photography, food and code 😎
Do you want to know more? Visit my website!