Problem overview
The method addContact receives a phone book phoneBook, an object that maps names to phone numbers, a name and a phone number. It adds name with its number to the phone book and returns the phone book. The add happens only when name is not in the phone book yet. A name that is already there keeps its old number. The order of the entries does not matter.
The constraints say the phone book can be empty, names are single words made of English letters, and numbers look like "555-0142". Two people can share a number.
The examples:
- Adding
"Cara"with"555-0123"to a book that has Ana and Ben gives a book with all three, since Cara is new. - Adding
"Ben"with"555-0100"changes nothing. Ben keeps"555-0199". - Adding
"Max"to an empty book gives a book with one contact.
Approach
The key question is "is this name already a key?" The in operator answers it: name in phoneBook is true when the object has that key. We want to add only in the opposite case, so we negate the check.
The reason to check at all is that assigning to an existing key replaces its value. A plain phoneBook[name] = number would overwrite Ben's old number with the new one, which this task forbids. The if guards the assignment.
Step by step
- Write an
ifthat checks thatnameis not a key ofphoneBook: put!in front of the wholeincheck, wrapped in parentheses. Write the closing brace right away. - Inside the
if, storenumberunder the keyname. Assigning to a key that is not there yet adds it, with its value. - After the closing brace, return
phoneBook. It either has the new contact, or it is as it was.
The solution in JavaScript
class Solution {
addContact(phoneBook, name, number) {
if (!(name in phoneBook)) {
phoneBook[name] = number;
}
return phoneBook;
}
}
Details worth knowing
The parentheses matter. Without them, !name in phoneBook applies the ! to the name alone, which gives false, and then asks whether the key "false" exists. That is false unless the book has a key named "false", so the if almost never runs and no contact is added.
The square brackets use the variable's value as the key. phoneBook[name] with name = "Cara" means the key "Cara", whereas phoneBook.name would mean a key literally called "name".
The method changes the object it was given and returns that same object.
Testing
Running the method on the three examples and printing each result with JSON.stringify gives:
{"Ana":"555-0142","Ben":"555-0199","Cara":"555-0123"}
{"Ana":"555-0142","Ben":"555-0199"}
{"Max":"555-0100"}
Edge cases and common mistakes
- Assigning without the check. The line
phoneBook["Ben"] = "555-0100"replaces Ben's number, and the result shows{"Ben":"555-0100"}instead of the old number. - Forgetting the parentheses. See above: the
!binds to the name, not to the whole check, and new contacts are never added. - Checking the values. The
inoperator looks at keys only. Two people may share a number, so a number being in the book says nothing about the name. - Returning inside the if. The
returnbelongs after the block, so it also runs when the name was already there.
