2010-08-26 8 views

risposta

22

Calcola la frequenza di ogni voce di prima.

{ 
    apples: 1, 
    oranges: 4, 
    bananas: 2 
} 

Quindi creare un array da questo oggetto di frequenza che rimuoverà anche i duplicati.

["apples", "oranges", "bananas"] 

Ora ordina questo array in ordine decrescente utilizzando la mappa di frequenza creata in precedenza.

function compareFrequency(a, b) { 
    return frequency[b] - frequency[a]; 
} 

array.sort(compareFrequency); 

Ecco l'intera sorgente (utilizzando la recente introduzione Array functions in ECMA 5) e combinando le fasi di generazione de-duplicazione e sugli frequenza,

function sortByFrequency(array) { 
    var frequency = {}; 

    array.forEach(function(value) { frequency[value] = 0; }); 

    var uniques = array.filter(function(value) { 
     return ++frequency[value] == 1; 
    }); 

    return uniques.sort(function(a, b) { 
     return frequency[b] - frequency[a]; 
    }); 
} 

Idem come sopra usando il normale iterazione matrice.

function sortByFrequencyAndRemoveDuplicates(array) { 
    var frequency = {}, value; 

    // compute frequencies of each value 
    for(var i = 0; i < array.length; i++) { 
     value = array[i]; 
     if(value in frequency) { 
      frequency[value]++; 
     } 
     else { 
      frequency[value] = 1; 
     } 
    } 

    // make array from the frequency object to de-duplicate 
    var uniques = []; 
    for(value in frequency) { 
     uniques.push(value); 
    } 

    // sort the uniques array in descending order by frequency 
    function compareFrequency(a, b) { 
     return frequency[b] - frequency[a]; 
    } 

    return uniques.sort(compareFrequency); 
} 
+0

può valere la memorizzazione nella cache Array.length invece di controllo su ciascuna iterazione – second

+1

@secondo: si tratta di una buona ottimizzazione per dataset di grandi dimensioni. Alcuni browser potrebbero già farlo internamente. – Anurag

+0

Probabilmente è elegante come lo troverete. – palswim

1

La strategia di base:

Creare un oggetto da utilizzare come una tabella hash per monitorare la frequenza di ogni elemento dell'array da ordinare.

Creare un nuovo array contenente l'articolo, le coppie di frequenze.

Ordinare questa matrice in base alla frequenza in ordine decrescente.

Estrarre gli elementi da quella matrice.

Codice:

function descendingUniqueSort(toBeSorted) { 
    var hash = new Object(); 
    toBeSorted.forEach(function (element, index, array) { 
          if (hash[element] == undefined) { 
           hash[element] = 1; 
          } 
          else { 
           hash[element] +=1; 
          }}); 
    var itemCounts = new Array(); 
    for (var key in hash) { 
     var itemCount = new Object(); 
     itemCount.key = key; 
     itemCount.count = hash[key]; 
     itemCounts.push(itemCount); 
    } 
    itemCounts.sort(function(a,b) { if(a.count<b.count) return 1; 
     else if (a.count>b.count) return -1; else return 0;}); 

    return itemCounts.map(function(itemCount) { return itemCount.key; }); 
} 
2

mi è stato effettivamente lavorando su questo, allo stesso tempo - la soluzione mi è venuta è praticamente identico a quello di Anurag.

Tuttavia ho pensato che valesse la pena condividere perché avevo un modo leggermente diverso di calcolare la frequenza delle occorrenze, usando l'operatore ternario e controllando se il valore è stato contato ancora in un modo leggermente diverso.

function sortByFrequencyAndFilter(myArray) 
{ 
    var newArray = []; 
    var freq = {}; 

    //Count Frequency of Occurances 
    var i=myArray.length-1; 
    for (var i;i>-1;i--) 
    { 
     var value = myArray[i]; 
     freq[value]==null?freq[value]=1:freq[value]++; 
    } 

    //Create Array of Filtered Values 
    for (var value in freq) 
    { 
     newArray.push(value); 
    } 

    //Define Sort Function and Return Sorted Results 
    function compareFreq(a,b) 
    { 
     return freq[b]-freq[a]; 
    } 

    return newArray.sort(compareFreq); 
} 
+0

Il ciclo che utilizzo per contare la frequenza dei controlli di occorrenza rispetto a un valore costante e scorre attraverso la schiera al contrario. Ciò si dovrebbe eseguire più velocemente anche su array di grandi dimensioni. – John

5

// ritorna più frequente al meno frequente

Array.prototype.byCount= function(){ 
    var itm, a= [], L= this.length, o= {}; 
    for(var i= 0; i<L; i++){ 
     itm= this[i]; 
     if(!itm) continue; 
     if(o[itm]== undefined) o[itm]= 1; 
     else ++o[itm]; 
    } 
    for(var p in o) a[a.length]= p; 
    return a.sort(function(a, b){ 
     return o[b]-o[a]; 
    }); 
} 

// test

var A= ["apples","oranges","oranges","oranges","bananas","bananas","oranges"]; 
A.byCount() 

/* valore restituito: (Array) arance, banane, mele */

+1

Se si trattasse di una competizione di Code Golf, avresti vinto! – palswim

+0

Apprezzo davvero questo. Modificato per un ditt con i conteggi referencable per dict [term], grazie uomo. Grande aiuto, proprio quello di cui avevo bisogno – twobob

1
var arr = ["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"].sort(); 
var freq = {}; 
for (var s in arr) freq[s] = freq[s] ? freq[s] + 1 : 0; 
arr.sort(function(a, b) { return freq[a] > freq[b] ? -1 : 1; }); 
for (var i = arr.length - 1; i > 0; i--) if (arr[i] == arr[i - 1]) arr.splice(i,1); 
alert(arr.join(",")); 
1

per il primo passo per calcolare

{ 
    oranges: 4, 
    bananas: 2, 
    apples: 1 
} 

è possibile utilizzare la funzione di countBy underscroe.js

var all=["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"]; 
var frequency=_.countBy(all,function(each){return each}); 

così frequency oggetto conterrà la frequenza di tutti i valori unici, e si può ottenere una lista unica, semplicemente chiamando _.uniq(all), e di ordinare tale elenco unico con il metodo di sottolineatura _.sortBy e utilizzando l'oggetto frequency è possibile utilizzare

_.sortBy(_.uniq(all),function(frequencyKey){return -frequency[frequencyKey]}); 

-ve segno viene utilizzato qui per ordinare la lista in ordine decrescente per mezzo di valore di frequenza secondo il vostro requisito.

È possibile controllare la documentazione del http://underscorejs.org/ per un'ulteriore ottimizzazione per il proprio trucco :)

0

Per ES6, semplicemente codici con .filter e .sort come di seguito

> var arr = ["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"]; 
> arr.filter((key, idx) => arr.lastIndexOf(key) === idx).sort((a, b) => a < b ? -1 : 1); 
    ["apples", "bananas", "oranges"] 
Problemi correlati