Problem overview
The method addIfMissing gets a shopping list items, an ArrayBuffer[String], and a word item. It adds item at the end only when it is not in the list yet, and returns the list. The list may start empty.
For ["milk", "eggs"] and "bread", the word is new, so the result is ["milk", "eggs", "bread"]. For the same list and "milk", the word is already there and the list stays ["milk", "eggs"]. For an empty list and "apples", the result is ["apples"].
Approach
Ask first, then act. items.contains(item) says whether the word is there. You want to act when it is not, so put ! in front. Inside the if, items += item appends the word. Without the check, += adds the word every time, and ["milk"] becomes ["milk", "milk"].
Step by step
- Write the condition:
!items.contains(item)is true exactly when the word is missing. Open the block with{and close it with}. - Add the word inside it with
+=, which appends at the end. - After the
if, returnitems. When the word was already there, the list comes back as it was.
Why not just add it?
A plain items += item would always append, so a list that already has "milk" would end up with ["milk", "milk"]. A list that never holds the same word twice is the point of the task, as in a shopping list or a guest list. The check costs one line and keeps the list free of repeats. Note that the check looks at the whole list, not only the last item: contains searches every position, so a word near the front is found as well.
The solution in Scala
class Solution {
def addIfMissing(items: ArrayBuffer[String], item: String): ArrayBuffer[String] = {
if (!items.contains(item)) {
items += item
}
return items
}
}
Notes on the Scala:
items += itemon a mutableArrayBufferchanges the buffer itself. The same buffer is returned.- The
ifhas noelse. When the word is present, nothing happens and the method goes straight to thereturn. containscompares whole words and is case-sensitive, so"Milk"would count as new next to"milk". The constraints say every word is lowercase.
Edge cases and common mistakes
- An empty list.
containsisfalse, so the word is added. - Forgetting
!. Then the word is added only when it is already there, the opposite of the task. - Returning only inside the
if. If thereturnsits inside the braces, the other path has no value to give, and the compiler reports a type mismatch: foundUnit, requiredArrayBuffer[String]. Return after theif.
The method both changes the buffer and returns it. A caller can keep using the buffer it passed in, or use the returned value: they are the same object, and both show the new word.
Another way
Since an if is an expression in Scala, the method can also be written as one line: if (items.contains(item)) items else items += item. Both branches give the buffer, so the whole expression is the result. For ["milk"] and "milk" it gives ArrayBuffer(milk), and for "tea" it gives ArrayBuffer(milk, tea). The longer form is easier to read while you are learning.
Testing
[milk, eggs], "bread" -> milk eggs bread
[milk, eggs], "milk" -> milk eggs
[], "apples" -> apples
