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

Quiero saber que 2 aparece más en la matriz. ¿Cómo hago eso?Obtiene el elemento que aparece la mayoría de las veces en una matriz

+3

es que siempre matriz ordenada (como lo es en el ejemplo)? – Thilo

+1

Vea aquí mi respuesta de pseudocódigo: http://stackoverflow.com/questions/3774757/c-get-mode-from-list-of-integers/3774791#3774791 – paxdiablo

+1

Si la respuesta a la pregunta de @ Thilo es sí, los mismos elementos siempre estarán agrupados. Esto le permite recorrer la lista una vez que compara cada elemento con el anterior y llevar a cabo un recuento de la cantidad de mismos elementos que ha encontrado y el recorrido más alto encontrado en el camino. Al final del ciclo, tendrás tu respuesta. Esto se ejecutará en tiempo lineal. Si la respuesta a la pregunta de @ Thilo es negativa, primero ordena la lista, seguida de la estrategia anterior. – Asaph

Respuesta

27

Me gustaría hacer algo como:

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 - Muy bonito ... Pero usaría un bucle 'for' para bloquear casos de esquina donde el objeto de matriz tiene propiedades: http://jsfiddle.net/9eJd3/ –

+0

Sugeriría la adición de' if (store.hasOwnProperty (v)) 'en caso de que alguien haya decidido modificar el prototipo de Object o Array, ya que la gente parece estar muy interesada en eso por aquí; P –

+0

@no - Eso no es suficiente, ya que' store' puede tener su propiedades propias que ** no son ** valores de la matriz. (http://jsfiddle.net/vR5JK/). Sin embargo, un bucle 'for' hará el truco, ya que cualquier cosa fuera de los valores de la matriz no está incluida en' store [0] 'to' store [store.length] ' –

2

Realice un histograma, busque la clave para el número máximo en el histograma.

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'); 

Esto supone que no hay vínculos, o no le importa cuál es seleccionado.

+1

No obstante, si el conjunto está ordenado. Entonces puede ser una operación de un solo pase. – Thilo

+1

Como nota al margen, esto se llama el modo de la distribución. –

1

Si la matriz se ordena esto debería funcionar:

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

No es necesario pedir los valores, solo se agrupan. Se producen menos comparaciones si se comprueba la frecuencia actual del candidato _mode_ si (pv! = Cv) '. – greybeard

+0

@greybeard, hace arr.sort() hacer 'agrupamiento' bien? Sé que no se ordena tan bien para diferentes tipos, pero ¿se agrupa correctamente? – user2734550

0

Esta versión será dejar de mirar cuando el recuento es superior al número de elementos aún no contados.

Funciona sin ordenar la matriz.

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

Si la matriz contiene cadenas Pruebe esta solución

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

Lo resuelto de esta manera para encontrar el número entero más común

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

Como hay muchas otras respuestas, podría ser útil agregar una explicación de por qué es preferible su solución. Puede agregar una explicación haciendo clic en el botón "editar" ... –

+1

¿Arr.sort() siempre ordena correctamente el grupo de diferentes tipos en la matriz? – user2734550

+1

yes @ user2734550. arr.sort() puede ordenar grupos de diferentes tipos en la matriz correctamente. pero si se trata de soltero junto con números de dígitos múltiples, es posible que tenga que ordenar de esta manera: arr.sort (function (a, b) {return a- b;}) – Ashikodi

4

solución con énfasis a Array.prototype.forEach y la problema de obtener más de una clave si el conteo máximo se comparte entre más elementos.

Editar: Propuesta con un solo bucle.

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 solución bastante corto.

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

Esta es mi solución.

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

Esta solución devuelve una matriz de los números más aparecidos en una matriz, en caso de que aparezcan varios números en los momentos "máximos".

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

Todas las soluciones anteriores son iterativas.

Aquí hay un funcional versión mutación menos 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; 
}; 

Podría ser optimizada en situaciones específicas en las que el rendimiento es el cuello de botella, pero tiene una gran ventaja de trabajar con cualquier tipo de elementos de la matriz.

La última línea podría sustituirse 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]); 
}; 

para mayor claridad

Cuestiones relacionadas