2013-01-04 2 views
2

J'ai écrit une implémentation relativement compliquée de la fonction MODE.MULT de Microsoft Excel, qui renvoie un tableau des valeurs les plus fréquentes ou répétitives dans un tableau. Il est implémenté avec trois boucles, dont une imbriquée dans une autre, et je soupçonne qu'il y a une façon plus simple de s'y prendre. Pour information, il utilise _.uniq de Lo-Dash pour extraire des valeurs en double du tableau retourné.Comment puis-je améliorer cette implémentation de 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); 
} 

Pour des fins de test, MODEMULT([1,2,3,4,3,2,1,2,3]) devrait retourner [2,3]

Merci d'avance pour votre aide!

Répondre

4

Vous pouvez aller avec moins de boucles, bien qu'il y ait un impact sur l'utilisation de la mémoire que vous garderez compte sur toutes les entrées uniques dans la gamme originale:

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

Impressionnant! Exactement ce que je cherchais. Merci beaucoup pour votre aide. J'ai mis à jour mon code et vous ai donné du crédit sur http://stoic.com/formula –

+0

Merci ismael. Stoic a l'air génial! Je fais des conversions Excel -> Javascript depuis un certain temps (automatiquement en tant que phase de construction pour mes projets basés sur des outils personnalisés utilisant Apache POI), mais je n'ai pas vu de projets similaires aux vôtres. Une vraiment bonne trouvaille! – Roonaan

+0

Merci! Content que tu aimes ça. Nous pourrions utiliser de l'aide pour certaines des fonctions les plus complexes, en particulier les statistiques manquantes ;-) –

Questions connexes