Start learning free

LESSON 124 OF 675 · ARRAYS - CHALLENGES

Add If Missing in TypeScript: includes and push

Practice Read the full explanation

You get a shopping list items, an array of strings, and a word item. Add item at the end only when it isn't in the list yet. Return the list.

When item is already there, the list stays as it is. The list may start empty.

 

Example 1:

Input: items = ["milk", "eggs"], item = "bread"
Output: ["milk", "eggs", "bread"]
Explanation: The word "bread" is not in the list yet.
It goes at the end.

Example 2:

Input: items = ["milk", "eggs"], item = "milk"
Output: ["milk", "eggs"]
Explanation: The word "milk" is already there.
Nothing is added.

Example 3:

Input: items = [], item = "apples"
Output: ["apples"]
Explanation: The list is empty, so "apples" is new.
It becomes the only item.

 

Constraints:

  • items has 0 to 9 words: it may be empty.
  • item and every word in items are made of lowercase English letters.
STEP 1 OF 3
    Ctrl + Enter to check

    TYPESCRIPT · ARRAYS - CHALLENGES

    Add If Missing in TypeScript, explained

    Problem overview

    addIfMissing receives a shopping list items, an array of strings, and a word item. It adds item at the end only when the list does not already hold it, and returns the list. When the word is already there, the list stays as it is. The list may start empty.

    With ["milk", "eggs"] and "bread" the result is ["milk", "eggs", "bread"]. With "milk" instead, the result is ["milk", "eggs"]. With an empty list and "apples" the result is ["apples"].

    Approach

    Ask the array first, then act. items.includes(item) is true when the word is there, and ! turns that around. Only inside that condition does push add the word at the end. This way the list never gets the same word twice.

    Step by step

    1. Write the check. An if with the condition !items.includes(item). Close its brace right away so the next step goes inside it.
    2. Add the word. Inside the if, items.push(item) appends it.
    3. Return the list. The return goes after the if, so it runs in both cases: with the new word added, or with the list unchanged.

    The solution in TypeScript

    class Solution {
        addIfMissing(items: string[], item: string): string[] {
            if (!items.includes(item)) {
                items.push(item);
            }
            return items;
        }
    }

    On the three examples it returns:

    [ 'milk', 'eggs', 'bread' ] [ 'milk', 'eggs' ] [ 'apples' ]

    Why the order of the lines matters

    The check has to come before the push. Once the word is pushed, includes would always be true, so a check afterwards tells nothing. Asking first and then acting is a pattern you will meet whenever a collection must not hold duplicates.

    The parameter is named item and the array items: they differ by one letter, so read them carefully. items.includes(item) asks whether the whole list contains the single word.

    Why not just compare in a loop?

    You could walk the array yourself and set a flag when a word matches, then push if the flag is still false. That needs a loop, a variable and a second condition, and all of it only repeats what includes already does. When a method names the question you are asking, prefer it: the code reads like the sentence "if the list does not include the item, add it".

    Edge cases and common mistakes

    • Empty list. [].includes("apples") is false, so the word is added and becomes the only item.
    • Pushing without the check. ["milk", "eggs"] would become [ 'milk', 'eggs', 'milk' ] for the word "milk".
    • Returning inside the if. When the word is already there, the function would then return nothing. Put the return after the block.
    • Exact text. includes is case-sensitive, but the lesson's words are all lowercase.

    Another way and testing

    indexOf returns -1 when the word is missing, so if (items.indexOf(item) === -1) works the same way: it gives [ 'milk', 'eggs', 'bread' ] for "bread" and [ 'milk', 'eggs' ] for "milk". includes reads closer to the question being asked, so it is the better choice here.

    Calling the function twice with the same word shows the guard working. Starting from ["milk"], two calls with "bread" leave [ 'milk', 'bread' ], not two breads. Like push, the function changes the array it receives and returns that same array.

    Keep going with TypeScript500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free