Finding Things in an Array

Ask an array questions instead of writing a loop for each one, with includes and indexOf for an exact value, and find, findIndex, some and every for any test you write.

Apprentice · JavaScript · Updated

After this lesson you can

  • Check whether an array holds a value, and where, with includes and indexOf
  • Search an array with a test function, using find, findIndex, some and every

Key takeaways

  • includes answers yes or no: is this exact value in the array? indexOf says where it is, or gives -1 when it isn't there.
  • Check for -1 before you use an index from indexOf, because splice(-1, 1) removes the last item.
  • find gives back the first item that passes your test, or undefined. findIndex gives back its index, or -1.
  • some is true when at least one item passes the test, and every is true only when all of them do.

Is that song already on the playlist, so nobody adds it twice? Which is the first song over five minutes, so you know when to grab a snack? Is every song short enough for the drive to the lake? You could write a loop for each question, but arrays already have methods that answer them in one line. Apps ask these questions constantly: is this username taken, is this item already in the cart, has every box on the form been filled in.

Is it there? includes

includes answers a yes-or-no question: is this exact value in the array? It gives back true or false:

const playlist = ['Highway Sunrise', 'Gas Station Coffee', 'Desert Radio', 'Windows Down'];

console.log(playlist.includes('Desert Radio'));
console.log(playlist.includes('desert radio'));
console.log(playlist.includes('Desert'));

if (!playlist.includes('Mile Marker 9')) {
  playlist.push('Mile Marker 9');
}
console.log(playlist.length);
true
false
false
5

The match has to be exact. Capital letters count, so 'desert radio' isn't on the list, and part of a title isn't the title. The last lines add a song only if it isn't there yet: ! is read "not", so the condition reads "if the playlist does not include Mile Marker 9".

Where is it? indexOf

indexOf goes one step further: it tells you where the value is. It gives back the index of the first match, or -1 (read "minus one") when the value isn't in the array. -1 is never a real index, so it can only mean "not found".

const playlist = ['Highway Sunrise', 'Gas Station Coffee', 'Desert Radio', 'Windows Down'];

console.log(playlist.indexOf('Desert Radio'));
console.log(playlist.indexOf('Highway Sunrise'));
console.log(playlist.indexOf('Mile Marker 9'));
2
0
-1

An index is exactly what splice, from Adding and Removing Items, needs. Together they remove a song by its title, and the check for -1 is the important part:

const playlist = ['Highway Sunrise', 'Gas Station Coffee', 'Desert Radio', 'Windows Down'];

const index = playlist.indexOf('Gas Station Coffee');
if (index !== -1) {
  playlist.splice(index, 1);
}

console.log(playlist);
console.log(playlist.splice(-1, 1));
[ 'Highway Sunrise', 'Desert Radio', 'Windows Down' ]
[ 'Windows Down' ]

The last line shows why the check matters. A negative start counts back from the end, so splice(-1, 1) removes the last song. Without the if, asking to remove a song that isn't there would quietly remove Windows Down instead.

Try it. Make a file named search.js with a playlist of four songs. Print whether one song is on it, then the index of another, then the index of a song that isn't there.

Searching with a test: find

includes and indexOf look for one exact value. Often the question is looser: which is the first song longer than five minutes? For that, you write the test yourself, as a function that gets an item and gives back true or false. find runs the test on each item in order and gives back the first item that passes:

const songLengths = [214, 187, 305, 243, 330];

const firstLongSong = songLengths.find(seconds => seconds > 300);
console.log(firstLongSong);

const playlist = ['Highway Sunrise', 'Gas Station Coffee', 'Desert Radio'];
console.log(playlist.find(title => title.includes('Radio')));
console.log(songLengths.find(seconds => seconds > 600));
305
Desert Radio
undefined

seconds => seconds > 300 is an arrow function: for each length, it answers "is this one over 300?". find stops at the first true, so 330 is never reached. When nothing passes, find gives back undefined. In your textbook, a function that answers true or false like this may be called a predicate.

Where is the first match? findIndex

findIndex is to find what indexOf is to includes: it gives back the index of the first item that passes, or -1 when none does.

const songLengths = [214, 187, 305, 243, 330];

console.log(songLengths.findIndex(seconds => seconds > 300));
console.log(songLengths.findIndex(seconds => seconds > 600));
2
-1

The first song over five minutes is at index 2, the third song on the list.

Some or every?

Two more methods ask about the whole array and give back true or false. Think of the questions you'd ask in the car: "Is anyone hungry?" needs one yes; "Is everyone buckled up?" needs a yes from every person.

const songLengths = [214, 187, 305, 243, 330];

console.log(songLengths.some(seconds => seconds > 300));
console.log(songLengths.every(seconds => seconds > 300));
console.log(songLengths.every(seconds => seconds < 600));
true
false
true
  • some is true if at least one item passes the test: at least one song is over five minutes.
  • every is true only if all of them pass: not every song is over five minutes, but every song is under ten.

Try it. In search.js, add an array of five song lengths. Find the first song shorter than three minutes (180 seconds), and check whether every song is under seven minutes (420 seconds).

Which one answers your question?

Your question Method What you get back
Is this exact value in the list? includes(value) true or false
Where is this exact value? indexOf(value) its index, or -1
Which is the first item that passes my test? find(test) the item, or undefined
Where is the first item that passes my test? findIndex(test) its index, or -1
Does at least one item pass? some(test) true or false
Does every item pass? every(test) true or false

Check yourself

2 questions to try on the lesson page.

So what

These six methods turn questions about a list into one readable line each. Checking for duplicates, finding a match and making sure everything is valid come up in almost every app, from a playlist to a sign-up form.

Key terms

Cheat sheets

Related