Printing contents of sets included in a map - c++

I am writing a program that reads team names from a file and divides them into groups. Each group of size 4. I am using a:
map<int, set<string> > groups
Assume the team names to be countries names.
Now after entering all the team names into the resp. groups I want to print the contents of each group and this is where I am getting stuck.
Here is the full working code, I have written so far.
#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
void form_groups(vector<string>);
int main(){
srand(unsigned(time(NULL)));
string team_name;
vector<string> teams;
while (cin >> team_name)
{
teams.push_back(team_name);
}
random_shuffle(teams.begin(), teams.end());
form_groups(teams);
}
void form_groups(vector<string> teams)
{
map<int, set<string> > groups;
map<int, set<string> >::iterator it;
string curr_item;
int curr_group = 1;
int count = 0;
for(int i = 0; i < teams.size(); i++)
{
curr_item = teams.at(i);
count++;
if(count == 4)
{
curr_group += 1;
count = 0;
}
groups[curr_group].insert(curr_item);
}
cout << curr_group << endl;
for(it = groups.begin(); it != groups.end(); ++it)
{
}
}

Your approach is fine. By using map<int, set<string> >::iterator it you can access a the given <key,value> pair with it->first and it->second. Since set<string> is a standard container itself you can use an set<string>::iterator to traverse through the elements:
map<int, set<string> >::iterator map_it;
set<string>::iterator set_it
for(map_it = groups.begin(); map_it != groups.end(); ++map_it){
cout << "Group " << it->first << ": ";
for(set_it = map_it->second.begin(); set_it != map_it->second.end(); ++set_it)
cout << *set_it << " ";
cout << endl;
}

I think it is the iteration over the groups map that is your difficulty. Example of iterating over a map:
for (it = groups.begin(); it != groups.end(); it++)
{
// 'it->first' is the 'int' of the map entry (the key)
//
cout << "Group " << it->first << "\n";
// 'it->second' is the 'set<string>' of the map entry (the value)
//
for (set<string>::iterator name_it = it->second.begin();
name_it != it->second.end();
name_it++)
{
cout << " " << *name_it << "\n";
}
}

While iterating over a std::map<..>, it->first would give you the key, and it->second would give you the corresponding value.
You would need something like this to iterate over the map:
for(it = groups.begin(); it != groups.end(); ++it)
{
cout<<"For group: "<<it->first<<": {"; //it->first gives you the key of the map.
//it->second is the value -- the set. Iterate over it.
for (set<string>::iterator it2=it->second.begin(); it2!=it->second.end(); it2++)
cout<<*it2<<endl;
cout<<"}\n";
}

Related

How to print out a map with different types [duplicate]

I am writing a program that reads team names from a file and divides them into groups. Each group of size 4. I am using a:
map<int, set<string> > groups
Assume the team names to be countries names.
Now after entering all the team names into the resp. groups I want to print the contents of each group and this is where I am getting stuck.
Here is the full working code, I have written so far.
#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
void form_groups(vector<string>);
int main(){
srand(unsigned(time(NULL)));
string team_name;
vector<string> teams;
while (cin >> team_name)
{
teams.push_back(team_name);
}
random_shuffle(teams.begin(), teams.end());
form_groups(teams);
}
void form_groups(vector<string> teams)
{
map<int, set<string> > groups;
map<int, set<string> >::iterator it;
string curr_item;
int curr_group = 1;
int count = 0;
for(int i = 0; i < teams.size(); i++)
{
curr_item = teams.at(i);
count++;
if(count == 4)
{
curr_group += 1;
count = 0;
}
groups[curr_group].insert(curr_item);
}
cout << curr_group << endl;
for(it = groups.begin(); it != groups.end(); ++it)
{
}
}
Your approach is fine. By using map<int, set<string> >::iterator it you can access a the given <key,value> pair with it->first and it->second. Since set<string> is a standard container itself you can use an set<string>::iterator to traverse through the elements:
map<int, set<string> >::iterator map_it;
set<string>::iterator set_it
for(map_it = groups.begin(); map_it != groups.end(); ++map_it){
cout << "Group " << it->first << ": ";
for(set_it = map_it->second.begin(); set_it != map_it->second.end(); ++set_it)
cout << *set_it << " ";
cout << endl;
}
I think it is the iteration over the groups map that is your difficulty. Example of iterating over a map:
for (it = groups.begin(); it != groups.end(); it++)
{
// 'it->first' is the 'int' of the map entry (the key)
//
cout << "Group " << it->first << "\n";
// 'it->second' is the 'set<string>' of the map entry (the value)
//
for (set<string>::iterator name_it = it->second.begin();
name_it != it->second.end();
name_it++)
{
cout << " " << *name_it << "\n";
}
}
While iterating over a std::map<..>, it->first would give you the key, and it->second would give you the corresponding value.
You would need something like this to iterate over the map:
for(it = groups.begin(); it != groups.end(); ++it)
{
cout<<"For group: "<<it->first<<": {"; //it->first gives you the key of the map.
//it->second is the value -- the set. Iterate over it.
for (set<string>::iterator it2=it->second.begin(); it2!=it->second.end(); it2++)
cout<<*it2<<endl;
cout<<"}\n";
}

How to print all elements in a 2D map given the 1st index

As the title says I want to print out all the elements of "group1" in this 2D map. I tried this but I just get a huge error at the for loop.
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main(){
map<string,map<int,double> > myMap;
myMap["group1"][13] = 10.41;
myMap["group1"][15] = 31.2;
//print all elements in "group1"
for (map< string, map<int,double> >::const_iterator iter =
myMap["group1"].begin(); iter != myMap["group1"].end(); ++iter)
{
cout << iter->first << '\t' << iter->second << '\n';
}
return 0;
}
Any help would be appreciated, thanks!
The type of myMap["group1"] is map<int,double> and not map<string,map<int,double>>
Then your code would look somehow like this:
const map<int,double> &grp1map = myMap["group1"];
for (map<int,double>::const_iterator iter = grp1map.begin(); iter != grp1map.end(); ++iter)
{
cout << iter->first << '\t' << iter->second << '\n';
}
You can simplify this with auto:
auto &grp1map = myMap["group1"];
for (auto iter = grp1map.begin(); iter != grp1map.end(); ++iter)
{
cout << iter->first << '\t' << iter->second << '\n';
}
But anyway you should do it like this:
for (auto &elem : myMap["group1"] )
{
cout << elem.first << '\t' << elem.second << '\n';
}
You want an iterator to your internal map<int,double>, whereas you are trying to get and iterator to your outer map<string,map<int,double> >:
int main() {
map<string, map<int, double> > myMap;
myMap["group1"][13] = 10.41;
myMap["group1"][15] = 31.2;
//print all elements in "group1"
for (map<int, double>::const_iterator iter =
myMap["group1"].begin(); iter != myMap["group1"].end(); ++iter)
{
cout << iter->first << '\t' << iter->second << '\n';
}
return 0;
}

How to create table of grouped multimap key and associated values in c++

In below code I am grouping the multimap key with associated values using equal_range after insertion the elements in map based on Group1 and Group2.
As per my requirement I need to set these values in API interface based on key value association in below format.
i.e.
{"group1","pointcloud_min_z", "int_t","24"};
{"group1","pointcloud_max_z", "bool_t","true"};
{"group2","pointcloud_max_z", "double_t","13"};
{"group2","pointcloud_min_z", "double_t","20.0"};
Now the question is how to create table based on multiple grouped key data. in this scenario column is going to be always constant but based on data insertion/deletion in multimap rows will be added/removed. Here group1 and group2 are keys. kindly suggest selection of container and approach to convert the group in to table.
Code snippet
#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef multimap<string, string> StringToIntMap;
typedef StringToIntMap::iterator mapIter;
int main ()
{
StringToIntMap mymap;
mymap.insert(make_pair("Group2", "pointcloud_max_z"));
mymap.insert(make_pair("Group1", "pointcloud_min_z"));
mymap.insert(make_pair("Group2", "double_t"));
mymap.insert(make_pair("Group1", "int_t"));
mymap.insert(make_pair("Group2", "13"));
mymap.insert(make_pair("Group1", "pointcloud_min_z"));
mymap.insert(make_pair("Group2", "pointcloud_min_z"));
mymap.insert(make_pair("Group1", "bool_t"));
mymap.insert(make_pair("Group1", "true"));
mymap.insert(make_pair("Group1", "pointcloud_min_max_z"));
cout << "mymap contains:" << endl;
mapIter m_it, s_it;
for (m_it = mymap.begin(); m_it != mymap.end(); m_it = s_it)
{
string theKey = (*m_it).first;
cout << endl;
cout << " key = '" << theKey << "'" << endl;
pair<mapIter, mapIter> keyRange = mymap.equal_range(theKey);
// Iterate over all map elements with key == theKey
for (s_it = keyRange.first; s_it != keyRange.second; ++s_it)
{
cout << " value = " << (*s_it).second << endl;
}
}
return 0;
} // end main
enter code here
From your question it appears you want to store the records in the format (key,value). For this you can encapsulate the non-key columns in an object and store it in a multimap like (key, object*).
I have modified your code for the same as given below-
class DATA
{
public:
//control access to data members as needed
string name;
string type;
string value;
DATA(string name, string type, string value): name(name), type(type), value(value) {}
};
typedef multimap<string, DATA*> StringToIntMap;
typedef StringToIntMap::iterator mapIter;
int main ()
{
StringToIntMap mymap;
//insert record {"group1","pointcloud_min_z", "int_t","24"}
DATA *elem = new DATA("pointcloud_min_z", "int_t","24");
mymap.insert(make_pair("Group1", elem));
//insert record {"group1","pointcloud_max_z", "bool_t","true"}
elem = new DATA("pointcloud_max_z", "bool_t","true");
mymap.insert(make_pair("Group1", elem));
//insert record {"group2","pointcloud_max_z", "double_t","13"}
elem = new DATA("pointcloud_max_z", "double_t","13");
mymap.insert(make_pair("Group2", elem));
//insert record {"group2","pointcloud_min_z", "double_t","20.0"}
elem = new DATA("pointcloud_min_z", "double_t","20.0");
mymap.insert(make_pair("Group2", elem));
cout << "mymap contains:" << endl;
mapIter m_it, s_it;
for (m_it = mymap.begin(); m_it != mymap.end(); m_it = s_it)
{
string theKey = (*m_it).first;
cout << endl;
cout << " key = '" << theKey << "'" << endl;
pair<mapIter, mapIter> keyRange = mymap.equal_range(theKey);
// Iterate over all map elements with key == theKey
for (s_it = keyRange.first; s_it != keyRange.second; ++s_it)
{
cout << " value = " << (*s_it).second->name << ", "
<< (*s_it).second->type << ", "
<< (*s_it).second->value << endl;
}
}
//when done delete the record pointers from the multimap
return 0;
} // end main

map iterator not dereferencable

I am getting compile error "map/set" iterator not dereferencable". What is going on here?
#include<iostream>
#include<map>
using namespace std;
int main(){
map<int, int> m;
map<int, int>::iterator itr=m.begin();
itr->first = 0;
itr->second = 0;
cout << itr->first << " " << itr->second;
return 0;
}
The map is empty, so m.begin() is equal to the past-the-end iterator and is therefore invalid.
You first have to insert elements somehow (you can also do that implicitly by using operator[]) to make it useful.
Also, you cannot modify the key of an element like this. You would have to remove (erase) the element from the map and insert a new one with the new key.
Here's an example about that:
#include<iostream>
#include<map>
using namespace std;
int main(){
map<int, int> m;
// insert element by map::insert
m.insert(make_pair(3, 3));
// insert element by map::operator[]
m[5] = 5;
std::cout << "increased values by one" << std::endl;
for(map<int, int>::iterator it = m.begin(); it != m.end(); ++it)
{
it->second += 1;
cout << it->first << " " << it->second << std::endl;
}
// replace an element:
map<int, int>::iterator thing = m.find(3);
int value = thing->second;
m.erase(thing);
m[4] = value;
std::cout << "replaced an element and inserted with different key" << std::endl;
for(map<int, int>::iterator it = m.begin(); it != m.end(); ++it)
{
cout << it->first << " " << it->second << std::endl;
}
return 0;
}
Your map's empty! What your iterator is pointing to is undefined.
What you wanted to do is
int main(){
map<int, int> m;
m[0] = 0;
map<int, int>::iterator itr=m.begin();
cout << itr->first << " " << itr->second;
return 0;
}
Here you have not assign any value. and you can not change the key of itr->first of it. It can be read only. But you can edit itr->second.
map<int, int> m;
m[10]=0;
map<int, int>::iterator itr=m.begin();
itr->second=10;
cout << itr->first << " " << itr->second;

std::tr1::unordered_map is ordered instead

I'd like to have an unordered_map which contains the occurrences of each key; the problem is that, when I print myMap, it's ordered instead. I know it'd be better to use C++11, but I cannot for some reasons I'm not going to explain.
#include <iostream>
#include <tr1/unordered_map>
using namespace std;
using std::tr1::unordered_map;
main () {
unordered_map<int,int> myMap;
int counter, key;
cin>>counter;
for (int i=0; i<counter; i++) {
cin>>key; // Read key from keyboard
if (myMap.find(key) == myMap.end()) // If key is not already present in myMap
myMap[key] = 1; // Insert the new key with 1 occurrence
else
myMap[key]++; // Increment the current key occurrence
}
for (unordered_map<int,int>::const_iterator it = myMap.begin(); it != myMap.end(); ++it)
cout << "[" << it->first << "," << it->second << "] " << endl;
}