Skip to main content

Javascript Arrays and Functional Programming

12th October, 2022

Updated: 12th October, 2022

    I spent most of the last couple months drowned in python land. And while it was a nice and enjoyable ride, I decided to come back to my first love: javascript. (hard to believe I know)

    In this article, I'll be exploring functional programming concepts applied to js, and more specifically to arrays.

    When we talk about functional programming in JS, three functions come to mind: map, filter and reduce. So let's dive in and explain what they do and how they work.

    To illustrate the following examples, I will work with an Array of objects containing information about real fooball players.

    let footballPlayers = [
     {gender: "M", name: "Karim Benzema", age: 29, club: "Real Madrid CF", country: "Spain"},
     {gender: "M", name: "Samir Nasri", age: 29, club: "Sevilla FC", country: "Spain"},
     {gender: "M", name: "Hatem Ben Arfa", age: 29, club: "PSG", country: "France"},
     {gender: "M", name: "Radamel Falcao", age: 27, club: "AS Monaco FC", country: "France"},
     {gender: "M", name: "Riyad Mahrez", age: 25, club: "Leicester City FC", country: "England"},
     {gender: "M", name: "Sofiane Feghouli", age: 26, club: "West Ham United", country: "England"}
    ]

    Array.prototype.map

    Array.prototype.map takes a function with the current array item as an argument. It will essentially loop through the array it's called on and will return a new array with the results of the function.

    That was confusing I know, so let's look at an example: suppose we wanted to create an array from the original one with only names and ages as object keys, this is how we'd achieve it:

    let namesAndAges  = footballPlayers.map( player => {
       return {name: player.name, age: player.age }
    })

    If we console.log the namesAndAges we get:

    [ {name: "Karim Benzema", age: 29}, {name: "Samir Nasri", age: 29} ] # ...

    /Note: the length of the new array will always be equal to the length of the original one. If you have an array of 7 items, calling map on it will return an array of 7 items/

    Array.prototype.filter

    Just like map, filter takes a function with the current array item as its argument. And just like map, filter returns a new array. Only in this scenario, the new array will contain items that pass a specific test declared in the function.

    Example: Let's filter out all players younger than 27 years old.

    let oldPlayers      = footballPlayers.filter( player => player.age >= 27 )

    With ES6, we can even do this using one-liners. Isn't it sweet ? Purists will certainly appreciate that.

    Our test returns a boolean, if it's true the item is pushed to the new array else it's skipped and the loop continues to the next item. (In the above example, we're testing player.age to check if it's greater than 27)

    Array.prototype.reduce

    Now we get into the cool stuff. With reduce you can turn an array into absolutely anything you want. It takes two arguments, a function and what is called an accumulator (which will store the result of the function executed at each pass through the array). This accumulator can be an array, an object, a number (if you want to calculate a sum for example) or almost anything really.

    Example: Let's transform this array into an object with players sorted by country.

    let playersByCountry = footballPlayers.reduce( (players, player, index) => {
    
        if (player.country == "France") {
           players.france.push(player)
        }
        else if (player.country == "England") {
            players.england.push(player)
        }
        else if (player.country == "Spain"){
            players.spain.push(player)
        }
    
        return players
    
    }, {france: [], england: [], spain: []} )

    A few things to note:

    The function takes 3 arguments: A reference to the accumulator (some people use the word all to describe it), the current item being iterated over and its index.

    We must always return the accumulator so that at every pass we have an accurate representation of the final return value.

    Other Nuggets

    Array.prototype.every

    Will return true if every single item being iterated over passes a test, if as much as one fails, it returns false.

    Example: Check that every single player is male (no sexism here, promise)

    let allMales    = footballPlayers.every( player => player.gender === "M" )

    Array.prototype.some

    Will return true if some of the items in the array pass a certain test. It only returns false if none pass it.

    let over25      = footballPlayers.some( player => player.age > 25)

    Conclusion

    Functional programming is a great tool and will drastically improve your productivity as well as make your code cleaner, leaner, and more readable. (Try doing a filter with for loops !)

    There's a lot more that can be done with arrays in Javascript, I'll probably write an article on the other neat, magical methods that js offers to manipulate them.

    Questions ? Found a Typo ? Spotted a mistake ? I'm @zabanaa on twitter.

    2020 - A blog by Karim Cheurfi


    c22e9f29-d68d-4586-9763-e750cc46fcb6

    Created on: 12th October, 2022

    Last updated: 12th October, 2022

    Tagged With: