Using map and reduce functions (using arrow notation) instead of for loops to work with an array

Hi all,

This is a question I’ve been practicing on to get better at JavaScript. The question entails finding out how many numbers in the array (nums) is smaller than each given item of the array (returning the answer in an array of equal size).

I solved it with a nested loop (one for cycling through each item and one for comparing each item to each other item), a score keeper variable (to count how many items it’s bigger than) and an if statement to compare the values of the items in turn.

The given numbers in the array are [8, 1, 2, 2, 3] and the expected array answer for these numbers is [4,0,1,1,3] .

8 is bigger than 4 other numbers
1 is bigger than 0 other numbers, etc.

Someone else posted the below answer, which looks really good and I’d like to get my head around the functions and acrobatics they used. I’d really appreciate some help deciphering that return line!

var nums = [8, 1, 2, 2, 3];
var smallerNumbersThanCurrent = function(nums) {
    return nums.map((n, i) => nums.reduce((a, c) => a + (nums[i] > c), 0))
};
console.log(smallerNumbersThanCurrent(nums))

This is what I (think!) I’ve figured out:

  1. the array nums is mapped: each of its items (n) and the next item (is i the next item of the array to which n is compared? in the description of map it should be the index of the item) is passed to a reducing function (arrow notation).

  2. the reducing function they’re passed to is going to return a single item. It first passes the two numbers to another function (to compare their sizes?).

  3. the other function adds the first value to the array item at index i, if that item plus the first value is bigger than the second item. What exactly is going on here? i.e. what does that bit of code do in plain language? I’m also not sure what function and parameter the 0 refers to.

I think the next step in understanding what’s going on here is to change the arrow notation to fully expanded functions, but it’s doing my head in trying to tease out the variables and what they’re referring to exactly.

This post is getting a bit long, so I’ll leave it at that for now. Any push in the right direction would be appreciated, thanks!

This is where the original question is posted:

https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/

i is the index of the current item. As mentioned in the documentation

looking at the documentation for reduce, we see the following syntax:

arr.reduce(callback( accumulator, currentValue, [, index[, array]] )[, initialValue])

a parameter is the accumulator. This variable will hold the number of items greater then the current item.

c is the currentValue.

0 is the initial value for the accumulator

notice how all parameter are one letter abbreviation of the parameter names in the documentation?

now lets decrompess the code a little bit:

var nums = [8, 1, 2, 2, 3];
var smallerNumbersThanCurrent = function(nums) {
    return nums.map((n, i) => {
        return nums.reduce((a, c) => {
           return a + (nums[i] > c)
        }, 0)
    })
};
console.log(smallerNumbersThanCurrent(nums))

this allows us to insert console.log() at any given point to see what the function is doing. You could also use a debugger to step through the code:

http://www.pythontutor.com/visualize.html#mode=edit

that can be really helpful

Lets first tackle this cheeky line:

 return a + (nums[i] > c)

so nums[i] will give the current value of where map is in the loop (we could just use n here as well)

which is then compared to the current value of where .reduce is. (reduce also loops over the array)

this comparison results in a Boolean value. if you do:

number + boolean

JS will type case the boolean to integer (1 for true, 0 for false). So a is increased by one of the comparison is true

if that is confusing, you could do:

if (nums[i] > c ) {
   a++
}

like a boss!! thank you!

so just one more question about the => representation, which is new to me.

is this function call:

nums.reduce((a, c) => { ... }

the same as this expanded version:

nums.reduce((a, c) = function (TheNextFunction) {   ...calculate and return a variable...  }

which then calls TheNextFunction defined somewhere else?

=> is called/named the arrow function expression. Its syntax introduced in es6, a massive JS language update in 2015

If you want to use an es5 function (function expression), you can do:

reduce(function(a, c) {  body of the function })