loading...

.map(), .filter(), and .reduce()

pickleat profile image Andy Pickle Updated on ・3 min read

Originally posted on my blog

For the last several weeks I've been applying for jobs. Sadly, the startup I was working at just didn't work out. I am super bummed it didn't work out, but that's how things go sometimes. Anyway, I've been posting on twitter that I'm looking around and such and I had a friend offer to do a mock interview.

Short story, he absolutely roasted me.

I'm so thankful that we did that, because I've honestly never been asked technical questions in an interview like that. I just cracked under the pressure. I wasn't that I don't know how to reverse a list. I just couldn't remember how to do it on demand.

So I've been reviewing some foundational JavaScript concepts because it'd be good for me to memorize what they do and how to use them. Instead of having to have to look it up each time. Yesterday I posted this code snippet in a tweet and it seemed to be pretty helpful to folks, so here's a bit more explanation.

.map()

Array.map()

from MDN:

The map() method creates a new array with the results of calling a provided function on every element in the calling array.

You have an array, and you need to do something to every element. That's what map is for!

let numbers = [1,2,3,4,5]
numbers = numbers.map(numb=> numb+1)
console.log(numbers)
// will be [2,3,4,5,6]

The big hurdle for me initially with any of this was realizing that numb was totally made up. You can call it anything you want. Common practice is to call the array the plural of whatever is contained in your array, and the singular item for each computation. I'll be honest, lots of this clicked for me by using a forEach() for a long time, instead. The difference between them is .map() returns an updated array. So in the example above, the numbers array has been rewritten with each value plus one. But if you wanted to keep your original numbers array, you would simply declare it to a new array like so let numbersPlusOne = numbers.map(numb=> numb+1).

Array.filter()

from MDN:

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

The main difference here, is that whatever condition you pass, will give you a mutated array of all the items that meet that condition.
For Example:

let numbers = [1,2,3,4,5]
numbers = numbers.filter(numb=> numb % 2 == 0)
console.log(numbers)
// will be [2,4]

Whatever condition you pass will be checked for each item in the array and it will be added to the new array and returned.

Array.reduce()

from MDN:

The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.

This one is just a bit more complicated, because there are more arguments. But in its simplest form you can take an array and perform the same function on each element to receive back a single value. Back to our numbers array

let numbers = [1,2,3,4,5]
numbers.reduce( (accumulator, currentValue) => accumulator + currentValue )
console.log(numbers)
// 15

Keep in mind the computation you do will be done on each item in the array, and the accumulator is the running total. There are also optional arguments of currentIndex and array that follow the currentValue (before the arrow function) but I won't get into those here.

Hope this helps!

Posted on Jul 16 '19 by:

pickleat profile

Andy Pickle

@pickleat

👋🏻I like JavaScript, React, Gatsby, NodeJS, and AWS. Personal interests include: specialty coffee, music, travel, and soccer.

Discussion

markdown guide
 

Hey,
Great job from your end. I prefer functional programming.Maybe because I have a Maths background and I dread for loops😉

One advice to make it easier for you to remember and also make your code more readable.
For example your filter should look something like this:


const evenNumbers = numbers.filter(number => number %2 === 0)

Just naming your variable correctly reduces the confusion.

One, you know the filter is returning even numbers. Also, it will quickly stick that you are just iterating over numbers and checking if each number is even. That way that variable wouldn't look made up. It will make perfect sense.

Best wishes.

 

Excellent contribution! I actually like to have this in hand, to remind me of that kind of stuff.

cheatography.com/costemaxime/cheat...

 

Very good input. I have a single critique, though, and this is ONLY because you're prepping: with reduce. Me, as a hiring person, I question deeper when candidates don't provide the third init value.

I know it's arguably pointless, especially when implicit inits come into play, but that's how it is. And you'll come across others who think the same.

To reiterate, this is gold. But those little things... A lot of times, hiring people will grab onto them and dig deeper. (Probably not what you want for a smooth-as-butter interview lol)

 

Interesting, I’d love to learn more, could you expound with an example?

 

I was on mobile last night and I've been busy today, so I honestly didn't expect to have a reply. ...but whaddaya know, I JUST NOW used a reduce lol.

The init value - technically - protects you from a TypeError if you encounter an empty array. init, if not provided, is implicitly taken from arr[0]. If !arr[0]... Muerte.

Here, I'm writing a cypress e2e test that finds all the card rows in the page and guarantees the contained cards are the same height. To do so, I sum the heights of all the cards, divide that by cards.length, and compare the final avg to cards[0]. (a variance inside will break the cards[0]===avg, I hope :D)

Not such a problem with Cypress, but it could be possible that there are no cards in the row.

Most uses of reduce aren't for summing, though. Its return - more often than not - is a complex object, rather than a simple value. In these cases:

  1. arr[0] can't properly init the product, because product and items have very different structures.
  2. providing an init that models the outcome helps self-document the code (other devs see in the call an idea of what to expect), and it save you a ton of checks internally.
it.only('cards within a row are equal-height', () => {
    cy.get('[data-t="card-row"]')
        .each(row => {
            let heights = []
            cy.wrap(row)
                .find('div.card')
                .each(card => heights.push(Math.floor(card.innerHeight())))
                .then(() => {
                    let avgHeight = heights.reduce((prev, curr) => prev + curr, 0) / heights.length
                    expect(heights[0]).to.eq(avgHeight)
                })
        })
})

Very cool! Thanks for sharing this example.

 

I still dont get the .reduce() 😔

 

Since you understand map but don't understand reduce, implementing map with reduce might help:

const map = (arr, func) => arr.reduce((acc, curr) => [...acc, func(curr)], [])

Edit: here's the same for filter:

const filter = (arr, func) => arr.reduce((acc, curr) => func(curr) ? [...acc, curr] : acc, [])
 

That’s ok! It took me a long time to get it. Reduce is useful because you get a single value returned from an array of values. For example, if you have an array and you need to total of all the numbers.

The accumulator is just the total up to that point and the currentValue is just the value at whatever index you are currently at. So if you are adding, it’ll be the total + the value and then repeat until it’s gone through every number in the array and return the value of the last operation. Hope this helps! Try playing with the MDN examples they may help too!

 

Hi Andy, I'm a newbie to JS so first of all, thanks for your contribution. Very useful stuff in here!
A common problem I encounter when reading documentation on JS is figuring out what words are actual keywords and what are the made up stuff.
Do you have any other example like the map() method?

 

Hey! I’ve seen this but haven’t had time to think of another example. Check the MDN docs linked in the article and you’ll find more!

 

Hey! Nice article!

I have a repository with some examples, if anyone is interested, check it out: github.com/pedroapfilho/array-methods

 

Hey there! I shared your article here t.me/theprogrammersclub and check out the group if you haven't already!