0

I have declared a set inside a map in c++ as std::map<std::string, std::set<std::string>>. How to loop to access or print the set values ?

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
Tanya
  • 45
  • 7
  • Maybe you should be using [`std::multimap`](http://en.cppreference.com/w/cpp/container/multimap) instead? – wilx Mar 29 '16 at 08:20

2 Answers2

2

If you know how to iterate a std::map or a std::set individually, you should have no troubles iterating them in combination. Note that if you iterate a std::map using a range-based for loop, you're iterating std::pair<K, V>s where K is the (const-qualified) type of the key and V the type of the values. If you only want to iterate a single set (associated with a a single key), simply access that element and iterate it as normal.

#include <iostream>
#include <map>
#include <set>
#include <string>

int
main()
{
  auto stuff = std::map<std::string, std::set<std::string>> {
    {"fruits",     {"apple", "banana", "orange"}},
    {"vegetables", {"carrot", "cucumber"}},
    {"nuts",       {"peanut", "walnut", "hazelnut", "coconut"}},
  };
  // Iterate over a single set
  for (const auto& s : stuff["fruits"])
    std::cout << s << "\n";
  std::cout << "\n";
  // Iterate over the whole data structure
  for (const auto& pair : stuff)
    {
      std::cout << pair.first << ":";
      for (const auto& s : pair.second)
        std::cout << " " << s;
      std::cout << "\n";
    }
}

Output:

apple
banana
orange

fruits: apple banana orange
nuts: coconut hazelnut peanut walnut
vegetables: carrot cucumber
5gon12eder
  • 24,280
  • 5
  • 45
  • 92
1

Presumably that you have a std::map<std::string, std::set<std::string>>, you can print the elements of the contained sets with a double ranged for loop as the example below:

std::map<std::string, std::set<std::string>> mp {{"1", {"1", "2", "3"}}, 
                                                 {"2", {"4", "5", "6"}}};

for(auto &&p : mp) {
  for(auto &&s : p.second) std::cout << s << " ";
  std::cout << std::endl;
}

Live Demo

Or if you want something more fancy to impress your boss you could use a single ranged for loop with std::copy and std::ostream_iterator:

std::map<std::string, std::set<std::string>> mp {{"1", {"1", "2", "3"}}, 
                                                 {"2", {"4", "5", "6"}}};

for(auto &&p : mp) {
  std::copy(std::begin(p.second), std::end(p.second), 
            std::ostream_iterator<std::string>(std::cout," "));
  std::cout << std::endl;
}

Live Demo

edit:

The goal is we have a table with camera name and specs as {std::map> cameraSpec {{"camera1, {"Spec1", "Spec2", "Spec3"}}, {"camera2", {"Spec2", "Spec4", "Spec6"}}}; and I want to write a code to check which specification is highly desirable to the user ? Something similar to finding the frequency of a word from the given table. How to access the specs?

How to access individual elements of the map

Say you want to access an existent element in the map (i.e., you're sure the specific key exists). You could use the map's subscript operator in the following way:

for(auto &&s : mp["camera2"]) {
  // you loop over elements {"spec2", "spec4", "spec6"}
}

That is, mp["camera2"] will return a reference to set in the map with values {"spec2", "spec4", "spec6"} under the key "camera2".

If you're not sure that a key exists in the map, then use the member function map::find. That is, first query the map if specific key you're looking for exists in it and then access the elements of the value/set in the same way as shown above:

auto it = mp.find("camera2");
if(it != mp.end()) {
  for(auto &&s : it->second) {
    // you loop over elements {"spec2", "spec4", "spec6"}
  }
}

Notice that if key "camera2" exists in your map, then map::find will return an iterator pointing to element associated with that particular key.

Now, the elements of the map are of type std::pair<const key_type, value_type> (in our case std::pair<const std::string, std::set<std::string>>).

If the key is not found std::map::find is going to return an iterator pointing to one pass the end element of the map.

std::pair has two members std::pair::first and std::pair::second. In our case std::pair::first value is equal to the key's value (i.e,. "cammera2") and std::pair::second is equal to the value under that key (i.e., the std::set with values {"spec2", "spec4", "spec6"}). That is why in the loop shown above we iterate over it->second (i.e., the value/set under key "cammera2").

101010
  • 41,839
  • 11
  • 94
  • 168