Maps

Stores pairs of information

Comparison with Vector

Example

map.put (key, value) 

map.get(key)

map.remove(key)

Member functions

m.put(key, value) m[key] = value O(log N) Inserts the key-value pair if the key does not already exist; else (if key already exists), overwrites
m[key] = value m[key] = value O(log N) Inserts the key-value pair if the key does not already exist; else (if key already exists), overwrites
m.get(key) m.at(key) O(log N) If key already exists, returns the corresponding value; raises exception if key was not present.
m[key] m[key] O(log N) If key already exists, returns the corresponding value; if key was not present, adds a default value for the key to m and returns it.
m.remove(key) m.erase(key) O(log N) If key exists, removes the key and associated value. Else, no effect.
m.containsKey(key) m.find(key) != m.end() O(log N) Returns true if key exists in m.

Map Example: Dictionary

ifstream file;  
promptUserForFile(file, "Where is your dictionary?");  
Map<string, string> dictionary;   
string word; 
  
while (getline(file, word)) {
    string definition;      
    getline(file, definition);      
    dictionary[word] = definition;  
}   
while (true) {
    string query = getLine("Word to look up?");       
    if (dictionary.containsKey(query)) {          
       cout << "The definition is " << dictionary[query] << endl;     
    } else {
       cout << "I don't know that word!" << endl;      
    }  
}   
Question: what if the user was also interested in the list of words for a given meaning? One option is to loop over maps; another option is to maintain a reverse map; we will look at both options one by one.

Looping over Maps

Map<string, int> phonebook;		
phonebook["Director"] = 12345678;	
phonebook["Dean"] = 98765432;	
...
		
//prints in alphabetical order  
for (string name : phonebook) { 
    int phoneNumber = phonebook[name]; 
    cout << "I’m going to call " << name; 
    cout << " at " << phoneNumber << endl;  
}
For C++ STL, the for-each loop iterates using key-value; access key using .first, access value using .second. example:
Map<string, int> phonebook;		
phonebook["Director"] = 12345678;	
phonebook["Dean"] = 98765432;	
...
		
//prints in alphabetical order  
for (pair<string, int> name_phone : phonebook) { 
    string name = name_phone.first;
    int phoneNumber = name_phone.second;
    cout << "I’m going to call " << name; 
    cout << " at " << phoneNumber << endl;  
}

Word Count

Given an input file, print each unique word with its frequency in lexicographic order.

Input in.txt:

to be or not to be
hello world
the world is not enough
i think therefore i am

Output:

am: 1
be: 2
enough: 1
hello: 1
i: 2
is: 1
not: 2
or: 1
the: 1
therefore: 1
think: 1
to: 2
world: 2

Program: int main() { ifstream infile("in.txt"); string word; Map<string, int> wc; while (infile >> word) { if (!wc.containsKey(word)) { wc[word] = 0; } wc[word]++; } for (string w : wc) { cout << w << ": " << wc[w] << endl; } }

Word Count sorted on word frequency

Example:

Input in.txt:

to be or not to be
hello world
the world is not enough
i think therefore i am

Output:

be: 2
i: 2
not: 2
to: 2
world: 2
am: 1
enough: 1
hello: 1
is: 1
or: 1
the: 1
therefore: 1
think: 1

Need to devise a solution where the frequency is the key. One solution: after constructing wc, create another map where the frequency is the key. But now, multiple words can have the same frequency, so what should be the value of this map? e.g., set<string>.

Map<int, Set<string>>
Could you use a Vector instead of Set. How about using a Queue or Stack?
int main()
{
  ifstream infile("in.txt");
  string word;
  Map<string, int> wc;
  while (infile >> word) {
    if (!wc.containsKey(word)) {
      wc[word] = 0;
    }
    wc[word]++;
  }
  Map<int, set<string>> wc_sorted;
  for (string w : wc) {
    int wfreq = wc[w];
    if (!wc_sorted.containsKey(wfreq)) {
      wc_sorted[wfreq] = Set<string>();
    }
    wc_sorted[wfreq].add(w);
  } 
  for (int wfreq : wc_sorted) {
    Set<string> words = wc_sorted[wfreq];
    for (string word : words) {
      cout << word << ": " << wfreq << endl;
    }
  }
}

Another example of nested ADTs

Problem: we want to schedule dinner with a group of our friends.