Conta elementi unici nella matrice senza ordinamento

In JavaScript il seguente troverà il numero di elementi nella matrice. Supponendo che ci sia almeno un elemento nell’array

arr = ["jam", "beef", "cream", "jam"] arr.sort(); var count = 1; var results = ""; for (var i = 0; i  " + count + " times\n" ; count=1; } } 

È ansible farlo senza usare sort () o senza modificare l’array in alcun modo? Immagino che l’array debba essere ricreato e quindi l’ordinamento potrebbe essere fatto sull’array appena creato, ma voglio sapere qual è il modo migliore senza ordinare. E sì, sono un artista, non un programmatore, tuo onore.

Un modo rapido per farlo è copiare gli elementi unici in un object.

 var counts = {}; for (var i = 0; i < arr.length; i++) { counts[arr[i]] = 1 + (counts[arr[i]] || 0); } 

Quando questo ciclo è completo, l'object counts avrà il conteggio di ciascun elemento distinto dell'array.

Il modo più veloce per farlo è con un new Set() object new Set() .

I set sono fantastici e dovremmo usarli più spesso. Sono veloci e supportati da Chrome, Firefox, Microsoft Edge e node.js.
Cosa è più veloce Set o Object? di Andrei Kashcha

Gli oggetti in un Set saranno sempre unici, in quanto conserva solo una copia di ogni valore inserito. Ecco una funzione che usa questa proprietà:

 function countUnique(iterable) { return new Set(iterable).size; } console.log(countUnique('banana')); //=> 3 console.log(countUnique([5,6,5,6])); //=> 2 console.log(countUnique([window, document, window])); //=> 2 

Questa espressione ti dà tutti gli elementi unici nella matrice senza mutarla:

 arr.filter(function(v,i) { return i==arr.lastIndexOf(v); }) 

Puoi concatenarlo con questa espressione per creare la tua stringa di risultati senza ordinare:

 .forEach(function(v) { results+=v+" --> " + arr.filter(function(w){return w==v;}).length + " times\n"; }); 

Nel primo caso il filtro accetta include solo l’ultimo di ogni elemento specifico; nel secondo caso il filtro include tutti gli elementi di quel tipo e .length fornisce il conteggio.

Perché non qualcosa come:

 var arr = ["jam", "beef", "cream", "jam"] var uniqs = arr.reduce((acc, val) => { acc[val] = acc[val] === undefined ? 1 : acc[val] += 1; return acc; }, {}); console.log(uniqs) 

Come questa soluzione , ma meno codice.

 let counts = {}; arr.forEach(el => counts[el] = 1 + (counts[el] || 0))