Question

I have written a relatively convoluted implementation of Microsoft Excel's MODE.MULT function, which returns an array of the most frequently occurring, or repetitive values in an array. It's implemented with three loops, including one nested into another, and I'm suspecting that there is a simpler way to go about it. For information, it's using _.uniq from Lo-Dash for extracting duplicate values out of the returned array.

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

For testing purposes, MODEMULT([1,2,3,4,3,2,1,2,3]) should return [2,3]

Thanks in advance for your help!

Was it helpful?

Solution

You could go with less loops, although there is an impact on memory usage as you will keep counts on all unique entries in the original range:

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top