2010-09-24 16 views
20
var store = ['1','2','2','3','4']; 

voglio scoprire che 2 appaiono come i più nella matrice. Come faccio a farlo?ottenere l'articolo che appare il più delle volte in un array

+3

è tale matrice sempre ordinato (come è nel tuo esempio)? – Thilo

+1

Vedi qui per la mia risposta pseudo-codice: http://stackoverflow.com/questions/3774757/c-get-mode-from-list-of-integers/3774791#3774791 – paxdiablo

+1

Se la risposta alla domanda di @ Thilo è sì, gli stessi elementi saranno sempre raggruppati insieme. Ciò ti consente di scorrere l'elenco una volta confrontato ogni elemento con il precedente e di tenere conto di quanti stessi elementi hai incontrato e della corsa più alta incontrata lungo il percorso. Alla fine del ciclo, avrai la tua risposta. Questo verrà eseguito in tempo lineare. Se la risposta alla domanda di @ Thilo è no, quindi ordina prima la lista, seguita dalla strategia sopra. – Asaph

risposta

27

vorrei fare qualcosa di simile:

var store = ['1','2','2','3','4']; 
var frequency = {}; // array of frequency. 
var max = 0; // holds the max frequency. 
var result; // holds the max frequency element. 
for(var v in store) { 
     frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency. 
     if(frequency[store[v]] > max) { // is this frequency > max so far ? 
       max = frequency[store[v]]; // update max. 
       result = store[v];   // update result. 
     } 
} 
+1

+1 - Molto bello ... Ma vorrei usare un ciclo 'for' per bloccare casi d'angolo in cui l'oggetto array ha proprietà: http://jsfiddle.net/9eJd3/ –

+0

Suggerirei l'aggiunta di' if (store.hasOwnProperty (v)) 'nel caso qualcuno abbia deciso di modificare il prototipo di Object o Array, visto che la gente sembra essere piuttosto entusiasta di farlo qui: P –

+0

@no - Non è abbastanza buono, dato che' store' può avere il suo possedere proprietà che ** non sono ** valori dell'array. (http://jsfiddle.net/vR5JK/). Un ciclo 'for' farà comunque il trucco, dal momento che qualsiasi cosa al di fuori dei valori nell'array non è inclusa in' store [0] 'per' store [store.length] ' –

2

Fare un istogramma, trovare la chiave per il numero massimo nell'istogramma.

var hist = []; 
for (var i = 0; i < store.length; i++) { 
    var n = store[i]; 
    if (hist[n] === undefined) hist[n] = 0; 
    else hist[n]++; 
} 

var best_count = hist[store[0]]; 
var best = store[0]; 
for (var i = 0; i < store.length; i++) { 
    if (hist[store[i]] > best_count) { 
    best_count = hist[store[i]]; 
    best = store[i]; 
    } 
} 

alert(best + ' occurs the most at ' + best_count + ' occurrences'); 

Questo presuppone che non vi siano vincoli o che non ti interessa quale sia selezionato.

+1

Non necessario se l'array è ordinato, però. Quindi può essere un'operazione a passaggio singolo. – Thilo

+1

Come nota a margine, questa è chiamata la modalità della distribuzione. –

1

Se l'array è ordinato questo dovrebbe funzionare:

function popular(array) { 
    if (array.length == 0) return [null, 0]; 
    var n = max = 1, maxNum = array[0], pv, cv; 

    for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i]) { 
     if (pv == cv) { 
     if (++n >= max) { 
      max = n; maxNum = cv; 
     } 
     } else n = 1; 
    } 

    return [maxNum, max]; 
}; 

popular([1,2,2,3,4,9,9,9,9,1,1]) 
[9, 4] 

popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10]) 
[10, 5] 
+0

I valori non devono essere ordinati, solo raggruppati. Un minor numero di confronti si verifica se la frequenza corrente di _mode candidate_ è selezionata 'if (pv! = Cv)'. – greybeard

+0

@greybeard, arr.ort() fa "raggruppare" bene? So che non è adatto a tipi diversi, ma raggruppa correttamente? – user2734550

0

Questa versione si chiuderà guardando quando il conteggio supera il numero di elementi non ancora conteggiati.

Funziona senza ordinare l'array.

Array.prototype.most= function(){ 
    var L= this.length, freq= [], unique= [], 
    tem, max= 1, index, count; 
    while(L>= max){ 
     tem= this[--L]; 
     if(unique.indexOf(tem)== -1){ 
      unique.push(tem); 
      index= -1, count= 0; 
      while((index= this.indexOf(tem, index+1))!= -1){ 
       ++count; 
      } 
      if(count> max){ 
       freq= [tem]; 
       max= count; 
      } 
      else if(count== max) freq.push(tem); 
     } 
    } 
    return [freq, max]; 
} 

    //test 
    var A= ["apples","oranges","oranges","oranges","bananas", 
    "bananas","oranges","bananas"]; 
    alert(A.most()) // [oranges,4] 

    A.push("bananas"); 
    alert(A.most()) // [bananas,oranges,4] 
-1

Se l'array contiene stringhe provare questa soluzione

function GetMaxFrequency (array) { 
    var store = array; 
    var frequency = []; // array of frequency. 
    var result; // holds the max frequency element. 

    for(var v in store) { 
     var target = store[v]; 
     var numOccurences = $.grep(store, function (elem) { 
     return elem === target; 
     }).length; 
     frequency.push(numOccurences); 

    } 
    maxValue = Math.max.apply(this, frequency); 
    result = store[$.inArray(maxValue,frequency)]; 
    return result; 
} 
var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya']; 
alert(GetMaxFrequency(store)); 
0

ho risolto in questo modo per reperire il numero intero più comune

function mostCommon(arr) { 
    // finds the first most common integer, doesn't account for 2 equally common integers (a tie) 

    freq = []; 

    // set all frequency counts to 0 
    for(i = 0; i < arr[arr.length-1]; i++) { 
     freq[i] = 0; 
    } 

    // use index in freq to represent the number, and the value at the index represent the frequency count 
    for(i = 0; i < arr.length; i++) { 
     freq[arr[i]]++; 
    } 

    // find biggest number's index, that's the most frequent integer 
    mostCommon = freq[0]; 
    for(i = 0; i < freq.length; i++) { 
     if(freq[i] > mostCommon) { 
     mostCommon = i; 
     } 
    } 

    return mostCommon; 
} 
3
arr.sort(); 
    var max=0,result,freq = 0; 
    for(var i=0; i < arr.length; i++){ 
     if(arr[i]===arr[i+1]){ 
      freq++; 
     } 
     else { 
      freq=0; 
     } 
     if(freq>max){ 
      result = arr[i]; 
      max = freq; 
     } 
    } 
    return result; 
+0

Poiché ci sono molte altre risposte, potrebbe essere utile aggiungere una spiegazione sul motivo per cui la soluzione è preferibile. È possibile aggiungere una spiegazione facendo clic sul pulsante "modifica" ... –

+1

Arr.sort() ordina sempre correttamente un gruppo di tipi diversi nell'array? – user2734550

+1

si @ user2734550. arr.sort() è in grado di ordinare correttamente un gruppo di tipi diversi nell'array. ma se hai a che fare con singoli insieme con numeri a più cifre, potresti dover ordinare in questo modo: arr.sort (funzione (a, b) {return a- b;}) – Ashikodi

4

Soluzione con enfasi Array.prototype.forEach e la problema di ottenere più di una chiave se il numero massimo è condiviso tra più elementi.

Modifica: proposta con un ciclo, solo.

var store = ['1', '2', '2', '3', '4', '5', '5'], 
 
    distribution = {}, 
 
    max = 0, 
 
    result = []; 
 

 
store.forEach(function (a) { 
 
    distribution[a] = (distribution[a] || 0) + 1; 
 
    if (distribution[a] > max) { 
 
     max = distribution[a]; 
 
     result = [a]; 
 
     return; 
 
    } 
 
    if (distribution[a] === max) { 
 
     result.push(a); 
 
    } 
 
}); 
 
console.log('max: ' + max); 
 
console.log('key/s with max count: ' + JSON.stringify(result)); 
 
console.log(distribution);

-1

Una soluzione piuttosto breve.

function mostCommon(list) { 
 
    var keyCounts = {}; 
 
    var topCount = 0; 
 
    var topKey = {}; 
 
    list.forEach(function(item, val) { 
 
    keyCounts[item] = keyCounts[item] + 1 || 1; 
 
    if (keyCounts[item] > topCount) { 
 
     topKey = item; 
 
     topCount = keyCounts[item]; 
 
    } 
 
    }); 
 

 
    return topKey; 
 
} 
 

 
document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))

0

Questa è la mia soluzione.

var max_frequent_elements = function(arr){ 
var a = [], b = [], prev; 
arr.sort(); 
for (var i = 0; i < arr.length; i++) { 
    if (arr[i] !== prev) { 
     a.push(arr[i]); 
     b.push(1); 
    } else { 
     b[b.length-1]++; 
    } 
    prev = arr[i]; 
} 


var max = b[0] 
for(var p=1;p<b.length;p++){ 
     if(b[p]>max)max=b[p] 
} 

var indices = [] 
for(var q=0;q<a.length;q++){ 
    if(b[q]==max){indices.push(a[q])} 
} 
return indices; 

};

-1

Questa soluzione restituisce un array di numeri più che compaiono in un array, nel caso in cui più numeri appaiono ai tempi "MAX".

function mode(numbers) { 
     var counterObj = {}; 
     var max = 0; 
     var result = []; 
     for(let num in numbers) { 
     counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1; 
     if(counterObj[numbers[num]] >= max) { 
      max = counterObj[numbers[num]]; 
     } 
     } 
     for (let num in counterObj) { 
     if(counterObj[num] == max) { 
      result.push(parseInt(num)); 
     } 
     } 
     return result; 
    } 
-1

Tutte le soluzioni sopra sono iterative.

Ecco un funzionale versione mutazione-meno ES6:

Array.prototype.mostRepresented = function() { 
    const indexedElements = this.reduce((result, element) => { 
    return result.map(el => { 
     return { 
     value: el.value, 
     count: el.count + (el.value === element ? 1 : 0), 
     }; 
    }).concat(result.some(el => el.value === element) ? [] : {value: element, count: 1}); 
    }, []); 
    return (indexedElements.slice(1).reduce(
    (result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result), 
    indexedElements[0]) || {}).value; 
}; 

Potrebbe essere ottimizzato in particolari situazioni in cui le prestazioni è il collo di bottiglia, ma ha un grande vantaggio di lavorare con qualsiasi tipo di elementi dell'array.

L'ultima riga potrebbe essere sostituito con:

return (indexedElements.maxBy(el => el.count) || {}).value; 

Con:

Array.prototype.maxBy = function(fn) { 
    return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]); 
}; 

per chiarezza

Problemi correlati