So you've got an array that you need whittled down to a few items or just one matching item? If so, then you'll probably use either find() or filter().

And it's worth your time to know when to use which one.

In this guide, I'll show you how to pick the right method when you're trying to extract just what you need from an array of objects.

TL;DR Use find() if you're looking for just one item. Use filter() if you want to match on multiple items.

Finding a Single Item

Let's say you've got an array of unique items. In this case, it's a list of account objects. Each account has a unique name and a unique ID.

The business requirement here is that you let the user select an account from a drop-down list or enter a new account name.

Of course, if the user enters a new account name, you want to make sure it doesn't exist. Otherwise, you'd have duplicate entries.

Or, better yet, if an account by that name already exists, just use that account rather than returning an error. Somehow the user missed that the account already exists.

In that case, you'd want to use find().

Why? Because you're only looking for a single match. You don't care about multiple matches.

In fact, you shouldn't have multiple matches because every name in the list of accounts is supposed to be unique.

So here's what that code looks like in one of my Angular classes:

  private getAccount(accountName: string): Account {
    let account: Account = null;

    if (accountName) {
      account = this.availableAccounts.find(a => a.name.toLowerCase() == accountName.toLowerCase());

      if (!account) {
        account = { name: accountName, id: null };
      }
    }

    return account;
  }

That method takes in an account name. Then it iterates through the array of existing Account objects to look for a match.

The code translates both the account name provided by the user and the account name for each object in the array to lower case. That way the match is case-insensitive.

Then it simply checks for a match against any of the existing account names. If it finds one, then that's what it returns.

And it's done.

The plus side of using find() is that you don't have to write extra code to just get the first element of an array that might only contain a single element anyway.

The downside? Well, you can't get multiple matches if that's what you're looking for.

That brings me to the next option.

Filtering to Get Multiple Items

If you need a leaner, meaner version of a large array that only matches on specific items, go with filter().

Let's say you've got a dropdown field that allows users to select an account for a contact in your CRM app. That dropdown field also supports type-ahead lookups.

When the user starts typing the name of one of the accounts in the dropdown, the list shrinks to only match items that begin with the letters the user typed. In other words, standard type-ahead stuff.

That's when you'd want to use filter(). Because if the user types the letter "T" and you have more than one account name in the dropdown that starts with the letter "T" you'd want to show them all. Not just one.

So in that case you've got code that looks like this:

  private handleFetchAccountsResponse(accounts: Account[]) {
    this.availableAccounts = accounts;

    this.filteredAccounts = this.basicInfoFormGroup.controls['account'].valueChanges.pipe(
      startWith(''),
      map(value => this.filterAccount(value))
    );
  }

  private filterAccount(name: string): Account[] {
    const filterValue = name.toLowerCase();
    return this.availableAccounts.filter(account => account.name.toLowerCase().indexOf(filterValue) === 0);
  }

The first method sets the filteredAccounts. It's an Observable that's going to listen for changes in the type-ahead field. And when a user does type something there, it will update the filter so that the application only displays items that match the user's text.

So, for example, if the user typed 'T' then the application will only show options that begin with the letter 'T.' And if the user typed 'TR' then the application would only show options that begin with the letter 'TR.' And so on.

The filterAccount() method you see above handles that exact process. Once again, it converts both text strings to lower case. Then it uses indexOf() to check for dropdown options that begin with the characters the user typed.

Anything with an indexOf() equal to 0 means that the string appears at the start of the account name. That's what you're looking for.

The filter here will return a smaller array of the original array. It could also return a completely empty array if nothing matches.

But the point here is that the array can be any size, up to the length of the original array. That's how filter() works.

The find() method, on the other hand, only gives you 0 or 1 item.

Wrapping It Up

Welp, that's it.

Now think about how you can use filter() vs. find() in your own applications.

And, of course, as always: have fun!