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
Metodo | Utilità | Ritorno |
---|---|---|
.includes | Ritorna true/false se il valore cercato esiste nell’array | bool |
.find | Ritorna il primo elemento dell’array che soddisfa il criterio di ricerca oppure undefined se non trovato | object|undefined |
.filter | Ritorna un nuovo array contenente gli elementi dal set originario che soddisfano il criterio di ricerca | Array |
.indexOf | Ritorna il primo indice dell’elemento nel set se esiste, altrimenti ritorna -1 | Number |
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.