Iteration and array transformation · Lesson 33 of 77 · practice

filter, find, some and every: asking questions of a collection

About 65 minutes.

By the end of this lesson you can

  • Use filter to build a shorter array containing only the elements that pass a test.
  • Use find to get the first matching element, and handle the case where there is none.
  • Use some and every to turn a whole collection into a single true or false.
  • State what some and every return for an empty array, and why.
  • Pick the right one of the four from the question you are actually asking.

Four questions you ask about a collection

Why it matters

map answered one question: what do these look like once changed? Most of the other questions you ask about a list are about selection rather than transformation, and there are only four of them worth naming.

Which ones match? Give me all of them. Which one matches? Give me the first. Does any of them match — yes or no? Do all of them match — yes or no? Those are filter, find, some and every, and between them they cover an enormous amount of everyday code.

All four take the same kind of callback: one that answers a yes-or-no question about a single element. A function like that is called a predicate. Writing the predicate once and handing it to whichever of the four matches your question is what makes this family so easy to use — the hard thinking goes into the test, not into the plumbing.

filter: keep the ones that pass

Explanation

array.filter(predicate) returns a new array holding only the elements for which the predicate returned a truthy value, in their original order. The original array is unchanged, exactly as with map.

The length is the difference. Where map's output is always as long as its input, filter's output is anywhere from zero to the full length. That is the entire point of it, and it is why 'use map to remove items' never works.

The predicate's return value is treated as truthy or falsy, not as strictly true or false. Returning 0, an empty string, null or undefined drops the element just as reliably as returning false. That is usually convenient and occasionally a trap, so make your predicates return real comparisons rather than relying on a value's truthiness by accident.

find: the first one, or undefined

Explanation

array.find(predicate) returns the first element for which the predicate is truthy, and stops looking. If nothing matches, it returns undefined. Note the difference from filter carefully: find gives you an ELEMENT, filter gives you an ARRAY that might happen to contain one element.

Because find stops at the first match, it does less work than filter on a large array — but the real reason to prefer it is that it says what you mean. Writing users.filter(isAdmin)[0] forces the reader to work out that you wanted one, and it quietly builds a whole array to throw it away.

The undefined return needs handling. Reading a property off the result crashes with a TypeError when there was no match, and that crash usually happens in production rather than in your test data. Check the result before you use it, or use findIndex, which returns -1 rather than undefined when nothing matched and never tempts you into a property access.

some and every: one true-or-false answer

Explanation

array.some(predicate) is true when at least one element passes. array.every(predicate) is true when all of them do. Both return a plain boolean rather than a collection, which makes them the natural things to put inside an if.

Both also short-circuit. some stops at the first element that passes, because one is enough to answer the question. every stops at the first element that fails, for the same reason. On a long array where the answer is near the front, that is a large saving over building a filtered array and checking its length.

Their behaviour on an empty array is the part everybody gets wrong once, and it is not an accident of implementation — it follows from the questions. 'Is there at least one element that passes?' with nothing to check is no, so some returns false. 'Do all the elements pass?' with nothing to check is yes, because there is no counterexample, so every returns true. Mathematicians call the second one vacuous truth; in code it means an empty basket passes every validation you write, and if that is wrong for your program you must check for emptiness yourself.

An empty array is truthy

A common mistake

The classic filter bug is not in the filter. It is the line after it. const matches = items.filter(predicate); if (matches) { ... } always takes the branch, because every array is truthy — including an empty one. Test matches.length > 0, or use some when the question was really 'is there any?'.

The classic find bug is the mirror image: const user = users.find(predicate); console.log(user.name) throws a TypeError as soon as nothing matches, because undefined has no properties. And there is a sharper version of it — if the element you are searching for could itself be falsy, such as the number 0 in an array of scores, then if (found) is wrong even when find succeeded. Compare with undefined explicitly, or use findIndex and compare with -1.

Both bugs share a cause: treating a value as a yes-or-no answer when it is not one. If the question is yes-or-no, use the method that returns a boolean.

Pick the method that matches the question

A mental model

Say the question out loud before you type. 'All the ones that…' is filter. 'The first one that…' is find. 'Is there any…' is some. 'Are they all…' is every. If the sentence you said does not match the method you reached for, the code will read wrong to everyone who comes after you, even if it works.

This also protects you from the two-step habit of filtering and then looking at the result — .filter(p).length > 0 is .some(p), .filter(p).length === array.length is .every(p), and .filter(p)[0] is .find(p). Each rewrite is shorter, faster and more obviously correct.

Recap

Recap

All four take a predicate and leave the original array alone. filter returns a new, possibly shorter array. find returns the first matching element or undefined. some returns true if at least one passes and is false for an empty array. every returns true if all pass and is true for an empty array. Remember that an empty array is truthy, and that find's undefined must be handled before you touch a property on it.

Worked examples

Every output below was produced by actually running the code in the same sandbox your exercises run in — it is not a prediction.

Keeping only the rows that qualify

filter with a predicate over objects, then map to show what survived. The two methods together are the most common pair in this module.

1const stock = [2  { name: "pen", quantity: 12 },3  { name: "pad", quantity: 0 },4  { name: "clip", quantity: 4 },5];6 7const inStock = stock.filter((item) => item.quantity > 0);8 9console.log(inStock.length);10console.log(inStock.map((item) => item.name));11console.log(stock.length);
  • line 7

    The predicate answers one yes-or-no question about one item. filter decides what to do with the answers.

  • line 10

    filter then map: narrow the rows first, then pick the field. Reading it in that order is a habit worth forming.

  • line 11

    Still 3. filter built a new array and left this one alone.

What it prints

2["pen","clip"]3

find gives an element; filter gives an array

The same search written both ways, including the case where nothing matches. Watch what each one hands back when the answer is 'none'.

1const users = [2  { id: 1, name: "Ada" },3  { id: 2, name: "Bo" },4];5 6const found = users.find((user) => user.id === 2);7console.log(found.name);8 9const missing = users.find((user) => user.id === 99);10console.log(missing);11 12const missingAsArray = users.filter((user) => user.id === 99);13console.log(missingAsArray.length);14console.log(Boolean(missingAsArray));
  • line 7

    Safe here because we know id 2 exists. In real code you would check found first.

  • line 10

    undefined — not null, not an empty object. Reading .name off this line would throw a TypeError.

  • line 14

    true. An empty array is still truthy, which is why if (results) is never the test you wanted.

What it prints

Boundefined0true

some and every, including the empty case

Four one-line answers. The last two are the ones to remember: on an empty array some is false and every is true, and both results follow from the question each method asks.

1const ages = [22, 17, 31];2 3console.log(ages.some((age) => age < 18));4console.log(ages.every((age) => age < 18));5console.log(ages.every((age) => age > 10));6 7console.log([].some((age) => age < 18));8console.log([].every((age) => age < 18));
  • line 3

    17 passes, so at least one does: true.

  • line 4

    22 fails, so not all do: false. every stopped at the very first element.

  • line 7

    No element passed, because there were none to pass: false.

  • line 8

    True. There is no element that fails, so nothing contradicts the claim. This surprises everyone once.

What it prints

truefalsetruefalsetrue

Check yourself

Not scored, not stored. Getting one wrong is the useful part.

What does [].every((n) => n > 100) return?

A filter that matches nothing, followed by the check most people write first. Predict both lines.

const results = [1, 2, 3].filter((n) => n > 10);if (results) {  console.log("the if ran");}console.log(results.length);

You need to know whether any order in a list has the status "failed", and nothing more. Which is the best fit?

Write it yourself

Exercise · core · 6 tests

Select the active adults

Write a function called activeAdults that takes an array of person objects, each with name, age and active properties, and returns an array of the NAMES of the people who are both active (active is true) and 18 or older. Keep them in the order they appeared. An empty input, or an input where nobody qualifies, gives an empty array. Do not modify the array you were given.

What your code must do

activeAdults(people) returns a new array of strings, in the same relative order as the input. A person qualifies when active === true AND age >= 18, so exactly 18 qualifies. Everything else is excluded. The input array and its objects are unchanged.

Define activeAdults at the top level of your code — the tests call it by name.

Runs on your device in a sandbox with no network and no access to this page.

Exercise · core · 9 tests

Three questions about one list

You are given arrays of item objects, each with name and quantity. Write three functions. firstOutOfStock(items) returns the first item OBJECT whose quantity is 0, or null if there is none. hasOutOfStock(items) returns true if at least one item has a quantity of 0. allInStock(items) returns true if every item has a quantity greater than 0. Each one should use the method that matches its question. Think carefully about what each should answer for an empty array.

What your code must do

firstOutOfStock returns the item object itself (not a copy and not its name), or null — note that find returns undefined, so you must convert. hasOutOfStock([]) is false. allInStock([]) is true, following every's rule for empty collections. None of the three modifies the array or the items.

Define firstOutOfStock, hasOutOfStock and allInStock at the top level of your code — the tests call them by name.

Runs on your device in a sandbox with no network and no access to this page.

Worth remembering

  • filter versus find — what does each return?

    filter returns a new ARRAY of every matching element, possibly empty. find returns the first matching ELEMENT, or undefined if there is none. Use find when you want one; .filter(p)[0] builds a whole array to throw it away.

  • What do some and every return for an empty array?

    some is false: there is no element that passes. every is true: there is no element that fails. Both follow from the question each one asks. If an empty collection should not pass your validation, check the length yourself.

  • Why is if (results) wrong after a filter?

    Every array is truthy, including an empty one, so the branch always runs. Test results.length > 0 — or better, ask the boolean question directly with some.

Check this lesson against the source

We wrote the explanation; we did not invent the facts. This is the page that backs them.

MDN — Array.prototype.filter()

Check there: filter returns a shallow copy containing only the elements for which the callback returns a truthy value, and does not modify the array it is called on.

MDN — Array.prototype.find()

Check there: find returns the first element satisfying the predicate, or undefined when none does.

MDN — Array.prototype.some()

Check there: some returns false for an empty array and stops at the first element that passes.

MDN — Array.prototype.every()

Check there: every returns true for an empty array and stops at the first element that fails.

MDN — Array.prototype.findIndex()

Check there: findIndex returns -1 rather than undefined when nothing matches.

Prefer to read the source in a structured breakdown? Turn this doc into a breakdown

0 of 2 exercises in this lesson solved on this device

Consent version 2026-07-31.1

Cookie preferences