Array Methods Continued

This article will go over 7 array methods.

  • .forEach()
  • .map()
  • .filter()
  • .find()
  • .some()
  • .every()
  • .reduce()

These methods work in much the same way. Once you learn one, the rest will become much easier to learn.

They are all used to prevent us from using for loops.

.forEach

Given the array:

var vegetables = ["carrot", "tomato", "lettuce"]

In the pass, to log all these strings to the console, we would write a for loop like so:

for (var i = 0; i < vegetables.length; i++) {
    console.log(vegetables[i]);
}

We can also, and more simply, use the forEach method like this:

vegetables.forEach(function(vegetable) {
    console.log(vegetable);
});

Every one of these methods will take a callback function that we will also call an "iterator function." If you aren't familiar with callbacks, pause this lesson and brush up. These array methods are a great way to practice callbacks.

.forEach is asking for a function that takes one argument. You should usually call this argument the singular version of the array's name. See the above example to see how that's done. You are defining how you will refer to each item in the array.

In the background, forEach is actually using a for loop for you. It loops through the array and preforms the function you wrote for every item in the array. In this case, we told it to just console.log every item.

Benefits vs a for loop

Less code
Simpler code
Less ways to mess it up

One more example.

In our last example, we used an anonymous function. In this example, watch how we define a function, and then pass through a reference to that named function.

var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

var sum = 0

function adder(number){
    sum += number; 
}

numbers.forEach(adder);

console.log(sum);

.map

Understand what this code snippet does.

var numbers = [1, 2, 3];
var doubledNumbers = [];

for (var i = 0; i < numbers.length; i++) {
  doubledNumbers.push(numbers[i] * 2);
}

console.log(doubledNumbers);

We are avoiding mutating our original array. This is good practice. We can use .map() to do this same thing, but simpler.

var doubledNumbers = numbers.map(function(number) {
  return number * 2;
} 

The callback function that we wrote goes through each item in the array, and pushes whatever was returned in the callback to the new array.

Another example
var people = [
    {name: "Bob", age: 31},
    {name: "Eric", age: 27}
]

var names = people.map(function(person){
    return person.name;
});

This is called a "pluck" because we are plucking properties from an array of objects. It's a very common use of .map().

.filter

Filter is awesome, but it does take a bit of concentration to understand. So, strap in!

We will use the following array:

var cars = [
    {make: "Ford", model: "E150", price: 10000},
    {make: "Chevy", model: "Camaro", price: 20010},
    {make: "Toyota", model: "Tacoma", price: 30900},
    {make: "Ford", model: "Explorer", price: 9000},
    {make: "Ford", model: "F250", price: 2400},
]

With filter, we can make a new filtered array. If we want an array of just the "Fords" we can. We will write the iterator function to return either true or false. The simplest way to do that looks like this:

var fords = cars.filter(function(car) {
    return car.make === "Ford";
})

car.make === "Ford" evaluates to true or false. .filter() then adds all the items that would evaluate to true and adds them to our array.

Question: What if you wanted to filter all the cars that cost less than $15,000?

Try to write this on your own before looking at the answer.

Answer:

var affordableCars = cars.filter(function(car) {
    return car.price < 15000;
}

.find

Hopefully you're getting use to these, and can start to guess what they do.

Let's use are car array from above again.

var cars = [
    {make: "Ford", model: "E150", price: 10000},
    {make: "Chevy", model: "Camaro", price: 20010},
    {make: "Toyota", model: "Tacoma", price: 30900},
    {make: "Ford", model: "Explorer", price: 9000},
    {make: "Ford", model: "F250", price: 2400},
]

We want to find a Camaro object in this array.

var searchCar = cars.find(function(car){
    return car.model === "Camaro";
}

Don't forget the return keyword with any of these methods.

.find() will iterate over the array until it finds the first item that returns true in the iterator function. If you want to find all that return true, we have some other cool methods.

.every and .some

every()

Every and some are very similar. So, I'll just give simple examples and explanations of each. They both return a boolean. Either true or false. I'll use the cars array again.

var areAllCarsReasonablyPriced = cars.every(function(car){
    return car.price < 100000
}

Given our current array, areAllCarsReasonablyPriced will be true. If any of the prices was over $100,000, it would return false.

It's like asking `10000 < 100000 && 20010 < 100000 && 30900 < 100000 etc.

.some()

.some() is like asking or

`10000 < 100000 || 20010 < 100000 || 30900 < 100000 etc.

.reduce

reduce() is very flexible, so that makes it a bit tricky.

One difference with reduce() is that it takes an initial value. Often this is the number 0, and empty array [], empty string "", or and empty object. If we want to sum numbers using reduce, we could do this.

var numbers = [3, 6, 2]

var total = numbers.reduce(function(previous, number){
    return previous + number;
}, 0)

//total would equal 11

but if we change our initial value, it will change what total is.

var numbers = [3, 6, 2]

var total = numbers.reduce(function(sum, number){
    return previous + number;
}, 4)

//total would equal 15

A good way to understand it will be to see a bunch of practical examples. First, let's do our number summing one we just did, but a bit more practical.

var trips = [{ distance: 34 }, { distance: 12 } , { distance: 1 }];

var totalDistance = trips.reduce(function(sum, trip){
    return sum += trip.distance;
}, 0);

Second, let's do the exact same thing as we did with map, but using reduce.

var people = [
    {name: "Bob", age: 31},
    {name: "Eric", age: 27}
]

var names = people.reduce(function(previous, person){
    previous.push(person);
    return person.name;
}, []);

/// -> names = ["Bob", "Eric"];

Notice that we can say .push() on previous. This is because previous starts as what we set our initial value as. In this case, [].

Now, we are going to use the reduce helper to create an object that tallies the number of sitting and standing desks. The object returned will have the form '{ sitting: 3, standing: 2 }'.

var desks = [
  { type: 'sitting' },
  { type: 'standing' },
  { type: 'sitting' },
  { type: 'sitting' },
  { type: 'standing' }
];

var deskTypes = desks.reduce(function(previous, desk) {
    if (desk.type === "sitting") previous.sitting++;
    if (desk.type === "standing") previous.standing++;
    return previous;
}, { sitting: 0, standing: 0 });

If you get it, you're done! Skip to the conclusion. If you some more, here it is:

We will now write a function called 'unique' that will remove all the duplicate values from an array.

For example, given the following array:
var numbers = [1, 1, 2, 3, 4, 4];
The function will return
[1, 2, 3, 4]
Hint: Use both the 'reduce' and 'find' helpers.

function unique(array) {
    return array.reduce(function(previous, item){
        if(!previous.find(function(foundItem){
            return item === foundItem;
        })) {
            previous.push(item);
        }
        return previous;
    }, []);
}

Conclusion

Hopefully after mastering these, you will write a whole lot less for loops. Use these in white board interviews, and you will impress your interviewer. Use these in your code, and you will write more readable code with less bugs.