Problem overview
The method addIfMissing gets a shopping list items (a list of strings) and a word item. It adds item at the end only when the word isn't in the list yet, and returns the list. When the word is already there, the list stays as it is. The list may start empty.
Examples:
["milk", "eggs"]with"bread"gives["milk", "eggs", "bread"].["milk", "eggs"]with"milk"gives["milk", "eggs"]. The word is already there.[]with"apples"gives["apples"].
Approach: ask first, then add
This is a question followed by an action. The question is "is the word missing?", which item not in items answers with True or False. The operator checks the list item by item and compares values. The action is items.append(item), which adds at the end. Only when the answer is True does the append run.
The empty list needs no special case. Nothing is in an empty list, so item not in items is True and the word is appended, which makes it the only item.
Step by step
- Write an
ifwhose condition isitem not in items. - Append
iteminside theif. When the word is already in the list, the body is skipped and nothing changes. - Return
itemsafter theif, so the line runs in both cases.
The solution in Python
class Solution:
def addIfMissing(self, items: List[str], item: str) -> List[str]:
if item not in items:
items.append(item)
return items
On the three examples it prints:
['milk', 'eggs', 'bread']
['milk', 'eggs']
['apples']
The return is indented at the level of the if, not inside it. Put inside the if, it would return nothing (None) whenever the word was already there. Also remember that append returns None: write items.append(item) on its own line, and never items = items.append(item).
Another way: return early
You can write the check the other way round and leave the function as soon as the word is found:
def add_if_missing(items, item):
if item in items:
return items
return items + [item]
It gives ['milk', 'eggs', 'bread'], ['milk', 'eggs'] and ['apples'] on the three examples. Here the last line builds a new list with items + [item], so the list passed in is not changed. The reference solution is the shorter of the two and keeps one return at the bottom.
Edge cases and common mistakes
- Putting the return inside the
if. When the word is already in the list, the function then returnsNone: the calladdIfMissing(["milk", "eggs"], "milk")would printNone. - Appending without the check.
["milk", "eggs"]with"milk"would become['milk', 'eggs', 'milk']. - Using
inwherenot inis needed. Then the word is added only when it is already there, which is the opposite of the task. - Text must match exactly.
"Milk"is a different word from"milk". The constraints use lowercase letters only, so this does not come up in the tests. - Making a new list.
items + [item]builds a new list and leavesitemsalone. For the first example it gives the right list, but it is a different one, and the original list is not changed. The reference solution changes the given list instead.
Testing
Try a word that is the first item of the list, one that is the last item, and the empty list. The single not in test handles all three the same way. Printing the result is enough to see the difference between an added word and an unchanged list.
