4

I am very new to programming, so forgive me for being such a noob. Any input is much appreciated. The challenge asks to find the mode in an array of numbers. Here is the code:

function findMode(arr) {
  var c = {};
  for (var i = 0; i < arr.length; i++) {
    c[arr[i]] = (c[arr[i]] || 0) + 1;
  }
  var mode;
  var max = 0;
  for (var e in c) {
    if (c[e] > max) {
      mode = e;
      max = c[e];
    }
  }
  return mode * 1;
}

So for example if you have an array of [1,1,5,5,7,10,3,3,3,3], it makes an object of {'1':2, '3':4, '5':2, '7':1, '10':1}. The code below it( for(e in c)) I understand it. Function basically returns the mode which is 3. What I am confused about is the following code:

c[arr[i]] = (c[arr[i]] || 0) + 1;

This code is responsible for creating the following object:

{'1':2, '3':4, '5':2, '7':1, '10':1}

Can someone please explain how it does that? How does it make the list of objects and keep count of each object name? I am very confused by it.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143

4 Answers4

4

var a = b || c; is a common idiom in JavaScript. What it means is:

  1. if b is a truthy value, a will receive b.
  2. if b is a falsy value, a will receive c.

(Look up "JavaScript truthy and falsy values" to understand this. Basically there are 6 things in JavaScript that are falsy. Everything else is truthy).

This is basically counting the number of occurrences of something.

If there wasn't a value assigned for c[arr[i]], it will be undefined. Being undefined, the expression (c[arr[i]] || 0) would result in 0, because undefined is a falsy value. Then, 0 + 1 results in 1. c[arr[i]] is now 1.

On the other hand, if there was a value assigned for c[arr[i]], then (c[arr[i]] || 0) would result that same value (let's say, 1, for instance). So (c[arr[i]] || 0) is then 1, since c[arr[i]] is 1 and 1 || 0 would result in 1, since 1 is a truthy value. Then you have 1 + 1 and c[arr[i]] is now 2.

You are counting occurrences of something. You started with 0, then 1, then 2.

Rafael Eyng
  • 4,720
  • 2
  • 33
  • 34
2

If you break it down, it does the same as:

var c = {};
for (var i = 0; i < arr.length; i++) {
  var a = arr[i];
  // count item for the first time
  if (c[a] === undefined) {
    c[a] = 1;
  // increment count
  } else {
    c[a] = c[a] + 1;
  }
}

You can keep going:

if (!c[a]) {
  c[a] = 1
} else {
  c[a] += 1
}

And more:

c[a] = c[a] ? (c[a] + 1) : 1

Until you get:

c[a] = (c[a] + 1) || 1 // OR passes because NaN (hacky)

Which could also be expressed as:

c[a] = (c[a] || 0) + 1
elclanrs
  • 92,861
  • 21
  • 134
  • 171
1

Let's break your code snippet down into its individual parts:

  • c[arr[i]]: This code does the same thing that using the dot notation would do (like arr.length). It's referring to a place in the object- in this case, an element in arr. For example, if arr = [3,6,8], and you say c[arr[0]], you're trying to add this to the object: 3: .... For c[arr[1]], you would be trying to add 6: ... and so on. We have to use the brackets because we don't know what's at arr[i].
  • =: You know what that does, I'm hoping.
  • (c[arr[i]] || 0): This is saying, "if c[arr[i]] is a falsy value (like false, undefined, 0, "", etc.), then set c[arr[i]] to 0". If it was a truthy value (like true, 3, "string"), then c[arr[i]] would be set to itself- in other words, it wouldn't change. If the left side of || is truthy, c[arr[i]] is set to that, otherwise, it's set to the right side of ||, which is 0 in this case. Here's a reference for how these logical operators work.
  • +1: Regardless of what (c[arr[i]] || 0) evaluated to, add 1 to whatever's in c[arr[i]] now.

If you're into ES6/ES2015/whatever they're calling it now, Map is perfect for these kinds of problems:

function findMode(arr) {
  let c = new Map();
  arr.forEach(elem => {
    c.set(elem, (c.get(elem) || 0) + 1);
  });
  let mode, max = 0;
  for (let [key, value] of c) {
    if (value > max) {
      mode = key;
      max = value;
    }
  }
  return mode;
}
findMode([1, 1, 5, 5, 7, 10, 3, 3, 3, 3]); // -> 3
Community
  • 1
  • 1
rioc0719
  • 303
  • 2
  • 11
0
c[arr[i]] = (c[arr[i]] || 0) + 1;

Piece by piece:

c is the name of the object which you can access the internal properties of using a [] instead of the usual . syntax you are probably familiar with in JS objects.

arr is the given array into the answer
i is the index in the for loop
arr[i] is a number in the list (eg 1)

c[arr[i]] means the value associated with the key arr[i] in object c. There is an = sign so we are assigning to that value

c[arr[i]] is also found on the other side of the equals sign so we are reading the value

And then we add one to it.

The || 0 basically means if c[arr[i]] is a "false" like value which in JS null is, then use 0 instead of null. This solves for the case where we haven't seen this number before.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Pierre Tasci
  • 450
  • 2
  • 8