Start learning free

LESSON 124 OF 678 · ARRAYS - CHALLENGES

Add an Item to an Array Only If It Is Missing in Swift

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 4
    Ctrl + Enter to check

    SWIFT · ARRAYS - CHALLENGES

    Add If Missing in Swift, explained

    Problem overview

    The method addIfMissing receives a shopping list items, an array of strings, and a word item. It adds item at the end only when it isn't in the list yet, and returns the list. When the word is already there, the list comes back as it was. The list may be empty.

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

    Approach

    Ask the array a question, then act on the answer. contains(item) is true when the array holds the word, so !items.contains(item) is true when the word is missing. Only in that case do you call append. Either way, you return the list.

    Step by step

    1. Parameters are constants in Swift, so make a copy that can change: var items = items.
    2. Write an if whose condition is !items.contains(item).
    3. Inside it, call items.append(item). This runs only for a new word, so the list never gets the same word twice.
    4. After the if, return items.

    The solution in Swift

    class Solution {
        func addIfMissing(_ items: [String], _ item: String) -> [String] {
            var items = items
            if !items.contains(item) {
                items.append(item)
            }
            return items
        }
    }
    

    On the three examples it prints:

    ["milk", "eggs", "bread"]
    ["milk", "eggs"]
    ["apples"]
    

    Language details

    • The copy is a real one. Arrays are values in Swift, so appending to the local items doesn't change the array the caller passed in.
    • The condition needs no parentheses, and the braces are required even for a single statement.
    • contains compares whole words and respects letter case, so "Milk" would count as a new word next to "milk". The constraints keep every word lowercase.
    • On an empty list, contains is false, so the first word is always added.

    Testing

    • ["milk"] with "milk" gives ["milk"]: a list of one, word already there.
    • ["milk"] with "tea" gives ["milk", "tea"]: the new word goes last, not first.
    • ["a", "b"] with "b" gives ["a", "b"]: the match is the last item, and it still counts.

    Running the method twice with the same word on an empty list, addIfMissing(addIfMissing([], "a"), "a"), gives ["a"]. Calling it again with the same word is harmless, which is the point of the check.

    Edge cases and common mistakes

    • Leaving out the !. Then the word is appended only when it is already there, which is the opposite of the task. With "bread" nothing would be added.
    • Appending first, checking later. After the append, contains is always true, so the check tells you nothing.
    • Skipping the copy. Calling append on the parameter itself is a compile error: cannot use mutating member on immutable value: 'items' is a 'let' constant.
    • Returning inside the if only. When the word is already there, the method must still return the list.

    If you later need this for a big collection where checking has to be fast, a Set answers "is it there?" much faster than an array. The array version is the right fit here because the list must keep its order and stay small.

    Cost

    contains may look at every item, and append adds to the end. With at most nine words, there is nothing to optimise.

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