Simple function returning 1 if the Mean = Mode, or 0 if not I'm trying to get better at javascript and have built a simple function that returns 1 if the mode is equal to the mean, and 0 if not. You can enter an array of numbers into the function:

// tests
meanMode([1,2,3]); - returns 0
meanMode([4,4,4,6,2]); - returns 1
meanMode([4,4,4,6,6,6,2]); - returns 0


To clarify, the mean is the middle number in the array, and mode most occurring number.

When I was writing this, I wondered whether I create too many variables and overcomplicate things. The problems I thought I might be making are:


There are too many variables
It's confusing and over complex
It can be hard to retrace my logic and know what the code does and why it's there


I have a few questions that I hope better coders than myself can answer, as I'm relatively new to javascript:


Was using a counts variable necessary?
Are all variable keywords (const &amp; let) optimal?
Is it wise to include comments to describe what the code does?
Was declaring the mode variable before assigning its value the best way? Its value depends on a condition


Before writing this I wrote a brief logic plan as follows:

Mode:


var uniqueVals with unique vals (set)
for each unique value (uniqueVals.map), count no of occurrences in arr (filter.length) &amp; store as an array
if all values are identical, return 0, otherwise get the most frequent &amp; store in variable (there may be cases with no mode)


Mean:


sum all numbers
divide by no of numbers


And:


if unique values length is same as arr length, return 0
if mean = mode, return 1


When people write programming, is it usually best to have a detailed plan to follow? I wonder whether there are any best practices that I could follow to improve my coding ability.

function meanMode(arr) {
    let uniqueVals = Array.from(new Set(arr));
    let counts = uniqueVals.map(function (c, i, a) {
        return arr.filter(function (c2) {
            return c2 == c
        }).length
    }); // [3,1,1]

    if (arr.every(sameValues)) {
        return 0;
    } else {
        var mode;

        // if highest number in counts appears just once, then there is a mode
        if ((counts.filter(function (x) { return x == (Math.max(...counts)) }).length) == 1) {
            mode = uniqueVals[counts.indexOf(Math.max(...counts))]; // scope issue?
        } else {
            return 0;
        }

        const mean = (arr.reduce(function (a, c) { return a + c })) / (arr.length);

        if (mode == mean) {
            return 1;
        } else {
            return 0;
        }
    }

    function sameValues(c, i, a) {
        return c == a[0];
    }
}
First of all, I don’t think this is reasonable:


  if unique values length is same as arr length, return 0


If your array consists of unique values only (e.g. [1, 2, 3, 4]), its mode is not unique, rather there is multiple modes (in this case [1, 2, 3, 4]). How you define what mode exactly means depends on your application so I’m going to ignore this for now.



Let’s look at your code. I’ll list some observations:


Function name. A name like meanEqualsMode would more clearly describe what the function does
Unused variables. There are a few unused variables. Line 3 uses three arguments for the map function’s callback, but the callback is only ever called with one argument: The current array element. You also never use i and a.
Single-letter variable names. This style of naming problematic for a variety of reasons. Most importantly, it’s harder to reason about your own code. For example, in line 21, the reduce function has a and c as callback arguments. sum and count would be better names.
Separation of concerns. Your meanMode function does multiple things. It calculates the mode and the mean. Instead, use separate functions to calculate the mode and mean separately. If your applications uses the check for equality of mode and mean a lot, this would be a third function calling the other two. I’ve done that in the updated code below.
Predictable results. You state that meanMode should return whether the mode and the mean are equal; however, it actually returns a Number (1 or 0). A comparison function (e.g. a function containing the words is, equal, or similar) should always return a boolean value (true or false). This again makes it easier to reason about your code. Just reading meanEqualsMode([2, 3, 5]) should tell you what the result of that function will be without the need to look at the actual implementation.




function meanEqualsMode(array) {
  const mode = arrayMode(array);
  const mean = arrayMean(array);

  return mode === mean;
}

function arrayMode(array) {
  const frequencies = new Map();

  for (const value of array) {
    const currentCount = frequencies.has(value) ? frequencies.get(value) : 0;
    frequencies.set(value, currentCount + 1);
  }

  let highestCount = 0;
  let mostOccurringValue;

  for (const [value, count] of frequencies) {
    if (count &gt;= highestCount) {
      highestCount = count;
      mostOccurringValue = value;
    }
  }

  return mostOccurringValue;
}

function arrayMean(array) {
  return array.reduce((sum, value) =&gt; sum + value) / array.length;
}


Now, answering some of your questions:


  Was using a counts variable necessary?


Yes and no. In order to calculate the mode of a list of numbers, you need to know the number of occurrences for each number. However, it is possible to determine the mode while counting the occurences; thus, allowing you to calculate the mode without explicitly storing the occurences. To keep the code simple, I opted for not combining these steps.


  Are all variable keywords (const &amp; let) optimal?


Probably not. You are using const and let. There is very, very little reason to also still use var at all. Most variables are assigned only once and can be defined using const. Some variables have to be declared using let because they’re (re-)assigned later.


  Is it wise to include comments to describe what the code does?


Yes. Take my code for example. Is there something you don’t understand? Then it could’ve maybe explained with a comment. You used a reduce function in your code which I often find hard to read. You need to ask yourself: Is my code dealing with a complex problem that needs explaining or is it just written in a hardly readable fashion? A complex problem is best explained with comments. Code which is hard to read and thus hard to reason about is better fixed by making it more readable and obvious.


  Was declaring the mode variable before assigning its value the best way? Its value depends on a condition


No, it wasn’t. The mode of a list of numbers always exists although it might not be unique. Therefor its value does not logically depend on a condition.