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 ?

1
  • Maybe you should be using std::multimap instead? Commented Mar 29, 2016 at 8:20

2 Answers 2

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
Sign up to request clarification or add additional context in comments.

Comments

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").

4 Comments

Is there a benefit to using r- value references here vs. const references?
@FredLarson is good habbit to use auto&& in for ranged loop. In this particular case it makes no difference.
@Tanya OK, what's the question?
@101010 Thank you so much. That was a good explanation. I appreciate it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.