Distinct su un array JavaScript
JavaScript non ha un metodo nativo per fare un distinct sugli elementi di un array.
Normalmente il codice per implementare un distinct è questo
Con la nuova istruzione Set si può raggiungere lo stesso scopo senza controllare l'esistenza (includes) in quanto un oggetto di tipo Set può contenere solo elementi univoci
Posso ulteriormente semplificare il codice passando l'array nel costruttore senza l'uso di forEach
con una sola riga ho implementato un Distinct su un Array JavaScript.
Per fare un distinct case insensitive la prima cosa che posso fare è convertire tutto in minuscolo (o maiuscolo)
Se voglio mantenere il case del primo elemento trovato posso usare 2 oggetti Set
Normalmente il codice per implementare un distinct è questo
JavaScript: Distinct Array
const arr = ["Mela", "Pera", "Arancia", "Kiwi", "Pera", "Mela"];
const result = [];
arr.forEach(item => {
if(result.includes(item) === false){
result.push(item);
}
});
console.log(result);
// Array(4): [ "Mela", "Pera", "Arancia", "Kiwi" ]
Con la nuova istruzione Set si può raggiungere lo stesso scopo senza controllare l'esistenza (includes) in quanto un oggetto di tipo Set può contenere solo elementi univoci
JavaScript: Distinct Set
const arr = ["Mela", "Pera", "Arancia", "Kiwi", "Pera", "Mela"];
const result2 = new Set();
arr.forEach(item => result2.add(item) );
console.log(result2);
// Set(4) [ "Mela", "Pera", "Arancia", "Kiwi" ]
Da notare il metodo add per aggiungere un elemento all'oggetto Set.
Visto che il risultato è un oggetto Set, se serve, posso convertirlo in Array tramite lo spread operator [... ]JavaScript: Distinct Spread
const result3 = [...result2];
console.log(result3);
// Array(4) [ "Mela", "Pera", "Arancia", "Kiwi" ]
Posso ulteriormente semplificare il codice passando l'array nel costruttore senza l'uso di forEach
JavaScript: Set constructor
const arr = ["Mela", "Pera", "Arancia", "Kiwi", "Pera", "Mela"];
const result4 = [... new Set(arr)]
console.log(result4);
// Array(4) [ "Mela", "Pera", "Arancia", "Kiwi" ]
Case insensitive
Il codice precedente funziona benissimo se devo fare un Distinct case sensitive.Per fare un distinct case insensitive la prima cosa che posso fare è convertire tutto in minuscolo (o maiuscolo)
JavaScript: Converto tutto un minuscolo
const arr5 = ["Mela", "Pera", "Arancia", "Kiwi", "PeRa", "mElA"];
const temp5 = new Set();
arr5.forEach(item => temp5.add(item.toLowerCase()) );
const result5 = [...temp5];
console.log(result5);
// Array(4) [ "mela", "pera", "arancia", "kiwi" ]
Se voglio mantenere il case del primo elemento trovato posso usare 2 oggetti Set
JavaScript: Mantengo il case del primo trovato
const arr6 = ["Mela", "Pera", "Arancia", "Kiwi", "PeRa", "mElA"];
const temp6 = new Set();
const temp6lower = new Set();
arr6.forEach(item => {
const itemLower = item.toLowerCase();
if(temp6lower.has(itemLower) === false) {
temp6.add(item);
temp6lower.add(itemLower) ;
}
});
const result6 = [...temp6];
console.log(result6);
// Array(4) [ "Mela", "Pera", "Arancia", "Kiwi" ]
Da notare l'uso del metodo has per controllare l'esistenza di un elemento.
Distinct su oggetti
Se voglio fare un Distinct basandomi su una o più proprietà di un oggetto posso usare il metodo findIndexJavaScript: Distinct Array Object
const arr7 = [{id: 1, tipo: "Mela"}, {id:2, tipo: "Pera"}, {id: 6, tipo: "Arancia"}, {id: 17, tipo: "Kiwi"}, {id: 8, tipo: "Pera"}, {id: 33, tipo: "Mela"}];
const result7 = [];
// result7.length=0
arr7.forEach(item => {
if(result7.findIndex(x => x.tipo.toLowerCase() === item.tipo.toLowerCase()) === -1) {
result7.push(item);
}
});
console.log(result7);
//Array(4) [ {…}, {…}, {…}, {…} ]
// 0: Object { id: 1, tipo: "Mela" }
// 1: Object { id: 2, tipo: "Pera" }
// 2: Object { id: 6, tipo: "Arancia" }
// 3: Object { id: 17, tipo: "Kiwi" }
In questo caso il confronto è case insensitive (toLowerCase).