2013-02-24 22 views
13

In JavaScript, il seguente numero troverà il numero di elementi nella matrice. Supponendo che vi sia almeno un elemento dell'arrayContare elementi univoci nella matrice senza ordinamento

arr = ["jam", "beef", "cream", "jam"] 
arr.sort(); 
var count = 1; 
var results = ""; 
for (var i = 0; i < arr.length; i++) 
{ 
    if (arr[i] == arr[i+1]) 
    { 
     count +=1; 
    } 
    else 
    { 
     results += arr[i] + " --> " + count + " times\n" ; 
     count=1; 
    } 
} 

È possibile fare questo senza usare sort() o senza mutare la matrice in qualche 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, vostro onore.

+0

La copia e l'ordinamento suona come una buona soluzione. Perché vorresti evitare questo? – Bergi

+2

È possibile inserire gli elementi in un dizionario e contare il numero di tasti. – zsong

+0

Voglio solo sapere un modo per aggirare questo. Sono solo curioso.In secondo luogo, incasina l'array originale, su cui si basano altri elementi. Potrei stare meglio trasformando la matrice in un oggetto. Ma non so cosa succederebbe alle varie parti di un oggetto di un certo tipo. –

risposta

30

Un modo rapido per eseguire questa operazione è copiare gli elementi univoci in un oggetto.

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

Quando questo ciclo è completo l'oggetto counts avranno il conteggio di ciascun elemento distinto della matrice.

+0

Funziona solo se gli elementi univoci sono stringhe (o convertiti in stringhe univoche) – Bergi

+2

@Bergi concessi, ma sono nell'esempio di OP. – kojiro

+0

Se si intende 'jam',' beef', 'cream' e' jam', sono variabili nell'esempio OPs. Non sappiamo cosa contengano – Bergi

5

Questa espressione fornisce tutti gli elementi unici nella matrice, senza mutare lo:

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

è possibile concatenare con questa espressione per costruire la vostra serie di risultati senza ordinare:

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

In 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 dà il conteggio.

+0

Sia 'filter' che' [last] indexOf' richiedono JavaScript 1.6. Questa risposta potrebbe utilizzare alcuni commenti esplicativi. – kojiro

+1

Il callback del filtro deve restituire un valore booleano, non l'elemento. E il ciclo for-each non corrisponde allo script originale degli OP – Bergi

7

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

I set sono fantastici e dovremmo usarli più spesso. Sono veloci e supportati da Chrome, Firefox, Microsoft Edge e node.js. .
- What is faster Set or Object? da Andrei Kashcha

Le voci di un Set sarà sempre unico, poiché si conserva una sola copia di ogni valore si mette in Ecco una funzione che utilizza 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

questo può essere usato per contare gli elementi in qualsiasi iterable (tra cui un Ar ray, String, TypedArray e oggetto arguments).

0

Perché non qualcosa di simile:

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)

puro JavaScript, viene eseguito in O (n). Non consuma molto spazio a meno che il tuo numero di valori unici sia uguale al numero di elementi (tutti gli elementi sono unici).

Problemi correlati