2013-01-04 8 views
2

Я написал довольно запутанную реализацию функции Microsoft Excel MODE.MULT, которая возвращает массив наиболее часто встречающихся или повторяющихся значений в массиве. Он реализован с тремя циклами, включая один вложенный в другой, и я подозреваю, что есть более простой способ сделать это. Для информации используется _.uniq от Lo-Dash для извлечения повторяющихся значений из возвращаемого массива.Как я могу улучшить эту реализацию MODE.MULT

function MODEMULT(range) { 
    var n = range.length; 
    var max = 0; 
    var counts = new Array(); 
    var result = new Array(); 
    for (var i = 0; i < n; i++) { 
    counts[i] = 0; 
    for (var j = 0; j < n; j++) { 
     if (range[j] === range [i]) { 
     counts[i]++; 
     max = (counts[i] > max) ? counts[i] : max; 
     } 
    } 
    } 
    for (var k = 0; k < n; k++) { 
    if (counts[k] === max) { 
     result.push(range[k]); 
    } 
    } 
    return _.uniq(result); 
} 

Для целей тестирования, MODEMULT([1,2,3,4,3,2,1,2,3]) должен возвращать [2,3]

Заранее спасибо за вашу помощь!

ответ

4

Вы могли бы пойти с меньшим количеством петель, хотя есть воздействие на использование памяти, как вы будете держать подсчет всех уникальных записей в исходном диапазоне:

function MODEMULT(range) { 
    var n = range.length, 
     // object to hold the number of occurrences per entry 
     count= {}, 
     // array to hold those numbers which have the current max occurrences 
     maxItems = [], 
     // reference to the current maximum 
     max = 0, 
     // JSLint placement of currentItem used inside the loop 
     currentItem; 

    for (var i = 0; i < n; i++) { 
    currentItem= range[i]; 

    // Update the occurrences table. 
    count[currentItem] = count[currentItem] ? count[currentItem] + 1 : 1; 

    // If a new maximum is created, void the original maxItems and update max. 
    if (count[currentItem] > max) { 
     max = count[currentItem]; 
     maxItems = []; 
    } 

    // If the entry reaches the current max, add it to maxItems. 
    if (count[currentItem] === max) { 
     maxItems[maxItems.length] = currentItem; 
    } 
    } 

    // No need for unique, as a duplicate value 
    // will increase max and thus empty out maxItems. 
    return maxItems; 
} 
+0

Awesome! Именно то, что я искал. Большое спасибо за Вашу помощь. Я обновил свой код и дал вам кредит на http://stoic.com/formula –

+0

Спасибо ismael. Стоик отлично выглядит! В течение некоторого времени вы делали Excel -> Javascript-конверсии (автоматически как этап сборки для моих проектов на основе пользовательских инструментов с использованием Apache POI), но не видели подобных проектов, подобных вашим. Поистине замечательная находка! – Roonaan

+0

Спасибо! Рад, что вам это нравится. Мы могли бы использовать некоторую помощь для некоторых более сложных функций, особенно отсутствующих статистических ;-) –