Problem overview
The method AddContact receives a phone book, a Dictionary<string, string> from names to phone numbers, plus a name and a phone number. It adds the name with its number and returns the phone book. The one rule: a name that is already in the book keeps its old number. The order of the entries does not matter, and the book may start empty.
With Ana and Ben in the book and the new name Cara, Cara is added with her number. With the name Ben and a new number "555-0100", nothing changes, and Ben keeps "555-0199". With an empty book and the name Max, the result has one contact, Max.
Approach
Assigning to a dictionary key, phoneBook[name] = number, does two different things depending on the key. If the key is new, it adds the entry. If the key exists, it replaces the old value. The task wants the first behavior only, so the assignment must be guarded: first ask whether the key is there, with ContainsKey, and assign only when it is not. The ! operator reverses the answer, so the guard is !phoneBook.ContainsKey(name).
An empty book needs no special case. ContainsKey on an empty dictionary is false, so the new name is added.
Step by step
- Write the guard. An
ifthat is true whennameis not a key ofphoneBook. Close its braces right away so the next step has a place to go. - Store the number inside it.
phoneBook[name] = number. Because the key is new, this adds the entry. - Return
phoneBookafter theif. It holds the new contact, or it is as it was when the name was already in it.
The solution in C#
class Solution {
public Dictionary<string, string> AddContact(Dictionary<string, string> phoneBook, string name, string number) {
if (!phoneBook.ContainsKey(name)) {
phoneBook[name] = number;
}
return phoneBook;
}
}
Running it on the three examples gives the dictionaries below. The lesson's tests print a dictionary as key: value lines sorted by key, and these outputs use the same form.
Ana: 555-0142
Ben: 555-0199
Cara: 555-0123
Ana: 555-0142
Ben: 555-0199
Max: 555-0100
The C# details worth knowing:
- The index setter replaces. That is why the guard is needed. Without it,
phoneBook["Ben"] = "555-0100"would overwrite Ben's number. Addthrows on a duplicate.phoneBook.Add("Ben", "555-0100")throws anArgumentExceptionwhen Ben exists, so it is no replacement for the check.TryAdddoes the same job in one call.phoneBook.TryAdd(name, number)adds the entry when the key is missing and returnsfalsewithout touching the book when it is there. The lesson teaches the explicitContainsKeycheck first, because it shows the logic.- The book is changed in place.
Dictionaryis a reference type, so the caller's book is the one that grows. The method returns the same object.
Edge cases and common mistakes
- No guard. A bare
phoneBook[name] = number;overwrites an existing contact. On the second example Ben would end up with"555-0100". - A missing
!.if (phoneBook.ContainsKey(name))only changes numbers that exist, and never adds a new contact. - Using
Addalone. It crashes on a name that is already there. - Checking the number. Two people can share a number, so the check is on the name (the key), not on the value.
ContainsValueis the wrong tool here. - An empty book. It works with the same code.
Testing
- Ana and Ben, add
"Cara"with"555-0123": three contacts. - Ana and Ben, add
"Ben"with"555-0100": Ben keeps"555-0199". - An empty book, add
"Max": one contact. - Add a second name with the same number as an existing contact: both are kept.
