Javascript Array Methods

John Wilson
7 min readFeb 3, 2017

--

Learning how to use the following built-in array prototype methods has been deemed by some as the gateway drug to functional programming.

  • Array.prototype.filter
  • Array.prototype.map
  • Array.prototype.sort
  • Array.prototype.reduce

Array.prototype.filter

Filter iterates over each item in an array. If a condition is met (and returned true) the item is returned to the original array. Pretty simple. If false is returned (or nothing is returned), the item is thrown away.

This means if an array has 10 items and filter only matches 6, only 6 items will be returned (different than Array.prototype.map).

Example

Use Array.prototype.filter to filter people with names greater than 4 characters.

Create an array of people with different length names.

const people = ['John','Tom','Bartholomew'];

Filter people with names greater than 4 characters.

people.filter(function(person) {
if (person.length > 4) {
return true;
}
})
// returns ['Bartholomew']

Or using arrow syntax.

people.filter(person => person.length > 4);// returns ['Bartholomew']

Summary

Filter provides a quick and easy way remove items in an array that do not match a specific criteria.

Array.prototype.map

Map also iterates over each item in an array but returns a new array of the same length.

Unlike filter which returns the original item (if returned true), map allows a new item to be returned of any value (usually based on the original item).

Also unlike filter if nothing is returned, the item is not thrown away, it is returned as undefined.

This means if an array has 10 items and map only returns 6 items, all 10 items will be returned, 4 being undefined.

Example

Use Array.prototype.map to add ‘Simpson’ as a last name to people only matching names greater than 4 characters.

const people = ['John','Tom','Bartholomew'];

Map over the people array.

people.map(function(person) {
if (person.length > 4) {
return person + ' Simpson';
}
})
// returns [undefined, undefined, 'Bartholomew Simpson']

Map returns undefined twice because ‘John’ and ‘Tom’ are greater than 4 characters and no value is returned when iterating over those 2 items.

If this is the case, why not use filter first to remove the unwanted items, then use map. See how functional programming can become addictive?

// Using arrow syntax to help readabilitypeople
.filter(person => person.length > 4) // removes 'John' and 'Tom'
.map(person => person + ' Simpson');
// returns ['Bartholomew Simpson']

Summary

Map iterates over each item of an array, performs an operation and returns a new value. The result is a new array the same length as the original array.

Array.prototype.sort

Sort orders an array of elements ascending or descending.

Example 1

Use Array.prototype.sort to sort an array of names.

const names = ['John', 'Tom', 'Bartholomew'];

Sort by name.

names.sort();// returns ["Bartholomew", "John", "Tom"]

Sort automatically sorts strings alphabetically. To get results in reverse, add the Array.prototype.reverse method.

names.sort().reverse();// returns ["Tom", "John", "Bartholomew"]

Example 2

Sort an array of ages.

const age = [13, 10, 7];

Sort by age.

people.sort();
// returns [10, 13, 7]

This is unexpected. The numbers are not sorted from lowest to highest.

This is because internally sort converts each value to a String. 10, 13, 7 become “10”, “13” and “7”.

In Unicode order, “10” and “13” come before “7”.

Well that is just great.

Fortunately, sort takes an optional compare function. This is great because it allows sort to really shine.

Example 3

Sort an array of ages, correctly this time using a compare function.

const age = [13, 10, 7];

Sort by age.

age.sort(function(a, b) {
return a - b;
})
// returns [7, 10, 13]

This is the correct result. By comparing each value with the next, the values are sorted and then returned in order.

Behind the scenes, sort is iterating over the array 2 values at a time. The first time a is 13 and b is 10.

  • If a - b is less than zero, a is sorted to a lower index.
  • If a - b is greater than 0, a is sorted to a higher index.
  • If a - b equals 0, then a and b are left unchanged.

This might seem complicated, but it is a simple way to sort arrays of Strings, Numbers and even Objects with nested properties.

The next example uses sort on an array of objects using a compare function to sort by age.

Example 4

Sort an array of objects by age.

const people = [
{name: 'John', age: 13},
{name: 'Tom', age: 10},
{name: 'Bartholomew', age:7}
];

Sort by age.

people.sort(function(a, b){
return a.age - b.age;
});
// returns [
{name: 'Bartholomew', age:7},
{name: 'Tom', age: 10},
{name: 'John', age: 13}
]

One last example sorting each person by name.

people.sort((a, b) => {
const aName = a.name.toUpperCase();
const bName = b.name.toUpperCase();
if (aName < bName) {
return -1;
}
if (aName > bName) {
return 1;
}
// names must be equal
return 0;
});
// returns [
{name: 'Bartholomew', age:7},
{name: 'John', age: 13}
{name: 'Tom', age: 10}
]

This last example converts each name to uppercase. This is so lowercase and uppercase characters are treated equally.

Summary

Sort reorders an array in ascending or descending order, based on a string representation of each value. When using numbers it can pose a problem, but a compare function can be used to order numbers. Objects can also use sort with a compare function to be sorted by any property.

Drink Break

Optionally, now is a time to fill up a cup of your favourite drink.

Array.prototype.reduce

Reduce iterates over an array and takes 2 arguments. The first is a callback that takes 4 arguments. The second is an initial value.

The callback function provides an accumulator, the current value, the current index and the array itself. These arguments are used to perform operations that reduce all values in the array to a single value.

The accumulator is just the running total that gets passed from each iteration to the next iteration. It is simply the value being returned (whatever is being returned) inside the reducer callback.

Finally, the initial value is the second argument of the reducer method. It is optional and can be used as a starting point for the final value.

Example 1

Understanding the accumulator.

const numbers = [10, 30, 60];numbers.reduce(function(accumulator, currentValue, currentIndex, array) {
console.log(accumulator);
return accumulator + currentValue;
},0)
// console.log shows 0 <- the initial value
// console.log shows 10 <- the initial value + currentValue, 10
// console.log shows 40 <- 10 + currentValue which is now 30
// console.log shows 100 <- 40 + currentValue which is now 60
// returns 100

The array has been reduced to a single value. The accumulator holds a running total each iteration and the current value is added to it.

To make the next examples easier to read, the argument names in the callback are shortened.

numbers.reduce(function(acc, val, i, array) {
// code here..
})

Example 2

Add the values in the array.

const people = [13, 10, 7];people.reduce(function(acc, val, i, array) {
return acc + val;
},0)
// returns 30

Example 3

Now to get a bit more complicated. Get the average number from all values in the array.

const people = [13, 10, 7];people.reduce(function(acc, val, i, array) {
if (i === array.length - 1) {
const numOfPeople = i + 1;
return ((acc + val) / numOfPeople)
}
return acc + val;
},0)
// returns 10

We have to check — is it the last iteration? If so we return the average of the final result based on the length of the array.

Remember i equals 0 the first iteration. By the final iteration i equals 2. But the array.length is equal to 3. So that is the reason for the syntax.

Example 4

Similar to the previous example, but with an array of objects.

Get the average age of people in the people array.

const people = [
{name: 'John', age: 13},
{name: 'Tom', age: 10},
{name: 'Bartholomew', age:7}
];
people.reduce(function(acc, val, i, array) {
if (i === array.length - 1) {
const numOfPeople = i + 1;
return ((acc + val.age) / numOfPeople)
}
return acc + val.age;
},0)
// returns 10

Example 5

This final example shows how to dynamically populate the initial value using the accumulator as data comes into the reducer.

const teams = ['teamA', 'teamA', 'teamB', 'teamC', 'teamC', 'teamC', 'teamD'];teams.reduce(function(acc, val, i, array) {
if (!acc[val]) {
acc[val] = 0;
}
acc[val]++;
return acc;
},{})
// returns {
teamA: 2,
teamB: 1,
teamC: 3,
teamD: 1
}

This last example checks to see if the accumulator has a property with the current value. If not, it creates it, then increases the value by 1. The final result is an object of teams with values based on number of times they appeared in the array.

Summary

Reduce takes an array and uses an accumulator and each value to reduce the data into a single value. The reduced value can be a Number or String. it can also be a dynamically generated object with properties and values. These are just a few of the possibilities using reduce.

Conclusion

I am not a master of these methods. I wanted to write this purely to force myself to take a closer look and learn more about them. I learned a lot while writing.

From simple filter and map to the more intricate sort and reduce, these methods can clean up code and make things easier to reason about.

I’m sure there are better ways of using these techniques above and beyond the levels in my examples. But if you have taken anything positive from reading this post, I hope it serves useful in your own work.

--

--