Transversing through a nested map - c++

How do I transverse through a nested map?
I want to access the value in the second nested map
int main ()
{
std::map<int, int> cool;
cool.insert(make_pair(8,9));
std::map<char, std::map<int, int> > mmap;
mmap.insert(std::make_pair('a', cool));
cout << mmap['a'][8];
std::map<char, map<int, int> >::iterator itr;
for(itr = mmap.begin(); itr != mmap.end(); itr++){
cout << itr->second << endl;
}
return 0;
}

Your itr points to a pair<char, map<int, int> >,
so its second is a map<int, int>,
so an iterator into that will do the trick:
for(map<int, int>::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2){
cout << itr2->second << endl;
}

With C++17 you can use structured binding to accomplish this:
for (auto const& [key, val] : mmap) {
for (auto const& [k, v] : val) {
std::cout << key << " " << k << " " << v << '\n';
}
}

Related

Problem with inserting vector elements into map?

While putting sorted vector elements into map, it inserts them in ascending order after it has been sorted in descending order with the compare function. I know that map is in ascending order by default based on its key, but I am not sure why it sorts them again in ascending order based on its value. Is this common in std::map<std::string, int>?
I simply want to return a map in descending order by its value, I need to display the directory strings with a number of items found by decreasing order.
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
bool compare_dir(std::pair<std::string, int>&a,
std::pair<std::string, int>&b)
{
return a.second > b.second;
}
void sort_func(std::map<std::string, int>& M)
{
std::map<std::string, int>::iterator itr;
std::vector<std::pair<std::string, int>> temp;
std::map<std::string, int> result;
for(auto &it : M)
temp.push_back(it);
sort(temp.begin(), temp.end(), compare_dir);
for(auto &el : temp)
std::cout << el.first << " " << el.second << std::endl;
std::cout << std::endl;
for(auto & el : temp)
result.insert(el);
for(itr = result.begin(); itr != result.end(); itr++)
std::cout << itr->first << " " << itr->second << std::endl;
}
int main()
{
std::map<std::string, int> my_map{{"dir1", 1}, {"dir2", 2}, {"dir3", 3}};
for (const auto& [key, value] : my_map) {
std::cout << '[' << key << "] = " << value << "; " << std::endl;
}
std::cout << std::endl;
sort_func(my_map);
}

How to use vector of map

vector <map<string,string>> dictionary;
map <string, string> word1;
map <string, string> word2;
word1.insert(pair<string, string>("UNREAL","Abc"));
word2.insert(pair<string, string>("PROPS","Efg"));
dictionary.push_back(word1);
dictionary.push_back(word2);
vector<map<string, string>>::iterator it;
it = dictionary.begin();
for( it; it != dictionary.end(); it++)
{
cout << it << " " << it << endl; //ERROR
}
I want to display the data stored in vector. Please suggest me how to display output from vector dictionary?
In order to solve your problem as it is, you should do this:
for(it = dictionary.begin(); it != dictionary.end(); it++){
for(auto it1=it->begin();it1!=it->end();++it1){
cout << it1->first << " " << it->second << endl;
}
}
However, I think there is something wrong with the design. In your case you do not need vector of maps... you need vector of pairs or just a map.
vector of pairs:
std::vector <std::pair<string,string>> dictionary;
dictionary.emplace_back("UNREAL","Abc");
dictionary.emplace_back("PROPS","Efg");
for(auto const& item:dictionary){
std::cout << item.first << " " << item.second;
}
map:
std::map<string,string> dictionary;
dictionary.insert("UNREAL","Abc");//also : dictionary["UNREAL"]="Abc";
dictionary.insert("PROPS","Efg");//also : dictionary["PROPS"]="Efg";
for(auto const& item:dictionary){
std::cout << item.first << " " << item.second;
}
Because map is not just a pair of something, it is a set of pairs (kind of not accurate).
// i is each map in your vector
for (auto i : dictionary) {
// j is each std::pair<string,string> in each map
for (auto j : i) {
// these are the two strings in each pair
j.first; j.second;
}
}
This answer requires c++11, but pretty much everything supports that these days.
vector and map are two containers, so you need two nested loops. In the nested loop over the map, your iterator refers to std::pairs so you access the key with .first and the value with .second:
vector <map<string,string> > dictionary;
map <string, string> word1;
map <string, string> word2;
word1.insert(pair<string, string>("UNREAL","Abc"));
word2.insert(pair<string, string>("PROPS","Efg"));
dictionary.push_back(word1);
dictionary.push_back(word2);
vector<map<string, string> >::iterator it;
for( it = dictionary.begin(); it != dictionary.end(); ++it)
{
map<string, string>::iterator it;
for( nested = it.begin(); nested != it.end(); ++nested)
{
cout << it->first << " " << it->second << endl; //ERROR
}
}
If you use C++11, you can make this shorter with Range-based for-loops:
vector <map<string,string>> dictionary;
map <string, string> word1;
map <string, string> word2;
word1.insert(pair<string, string>("UNREAL","Abc"));
word2.insert(pair<string, string>("PROPS","Efg"));
dictionary.push_back(word1);
dictionary.push_back(word2);
for(const map<string, string> &outer : dictionary)
{
for(const pair<string, string> & inner : outer)
{
cout << inner.first << " " << inner.second << endl; //ERROR
}
}
There is an answer on similar question here. The code will allow you to print any stl container with any template parameters using << operator.

C++ Loop through Map

I want to iterate through each element in the map<string, int> without knowing any of its string-int values or keys.
What I have so far:
void output(map<string, int> table)
{
map<string, int>::iterator it;
for (it = table.begin(); it != table.end(); it++)
{
//How do I access each element?
}
}
You can achieve this like following :
map<string, int>::iterator it;
for (it = symbolTable.begin(); it != symbolTable.end(); it++)
{
std::cout << it->first // string (key)
<< ':'
<< it->second // string's value
<< std::endl;
}
With C++11 ( and onwards ),
for (auto const& x : symbolTable)
{
std::cout << x.first // string (key)
<< ':'
<< x.second // string's value
<< std::endl;
}
With C++17 ( and onwards ),
for (auto const& [key, val] : symbolTable)
{
std::cout << key // string (key)
<< ':'
<< val // string's value
<< std::endl;
}
Try the following
for ( const auto &p : table )
{
std::cout << p.first << '\t' << p.second << std::endl;
}
The same can be written using an ordinary for loop
for ( auto it = table.begin(); it != table.end(); ++it )
{
std::cout << it->first << '\t' << it->second << std::endl;
}
Take into account that value_type for std::map is defined the following way
typedef pair<const Key, T> value_type
Thus in my example p is a const reference to the value_type where Key is std::string and T is int
Also it would be better if the function would be declared as
void output( const map<string, int> &table );
The value_type of a map is a pair containing the key and value as it's first and second member, respectively.
map<string, int>::iterator it;
for (it = symbolTable.begin(); it != symbolTable.end(); it++)
{
std::cout << it->first << ' ' << it->second << '\n';
}
Or with C++11, using range-based for:
for (auto const& p : symbolTable)
{
std::cout << p.first << ' ' << p.second << '\n';
}
As #Vlad from Moscow says,
Take into account that value_type for std::map is defined the following way:
typedef pair<const Key, T> value_type
This then means that if you wish to replace the keyword auto with a more explicit type specifier, then you could this;
for ( const pair<const string, int> &p : table ) {
std::cout << p.first << '\t' << p.second << std::endl;
}
Just for understanding what auto will translate to in this case.
As P0W has provided complete syntax for each C++ version, I would like to add couple of more points by looking at your code
Always take const & as argument as to avoid extra copies of the same object.
use unordered_map as its always faster to use. See this discussion
here is a sample code:
#include <iostream>
#include <unordered_map>
using namespace std;
void output(const auto& table)
{
for (auto const & [k, v] : table)
{
std::cout << "Key: " << k << " Value: " << v << std::endl;
}
}
int main() {
std::unordered_map<string, int> mydata = {
{"one", 1},
{"two", 2},
{"three", 3}
};
output(mydata);
return 0;
}
if you just want to iterate over the content without changing values
do:
for(const auto & variable_name : container_name(//here it is map name)){
cout << variable_name.first << " : " << variable_name.second << endl;
}
If you want to modify the contents of the map, remove the const and keep & (if you want to modify directly the contents inside container). If you want to work with a copy of the container values, remove the & sign too; after that, you can access them by using .first and .second on "variable_name".
it can even be done with a classic for loop.
advancing the iterator manually.
typedef std::map<int, int> Map;
Map mymap;
mymap['a']=50;
mymap['b']=100;
mymap['c']=150;
mymap['d']=200;
bool itexist = false;
int sizeMap = static_cast<int>(mymap.size());
auto it = mymap.begin();
for(int i = 0; i < sizeMap; i++){
std::cout << "Key: " << it->first << " Value: " << it->second << std::endl;
it++;
}
Other way :
map <int, string> myMap = {
{ 1,"Hello" },
{ 2,"stackOverflow" }
};
for (auto iter = cbegin(myMap); iter != cend(myMap); ++iter) {
cout << iter->second << endl;
}

iterate over multimap <string, map <string,int> >

i want to iterate over all items in a multimap <string,map<string,int>> but just once for each Key, but i cant make it work, here is the code im using to iterate:
for(multimap <string, map <string, int> >::iterator it = myMultimap.begin(); it != myMultimap.end(); it =myMultimap.upper_bound(it->first)){
//i read that myMultimap.upper_bound(it->first) get the elements of the same key
pair< multimap <string,map <string, int> >::iterator , multimap <string,map <string, int> >::iterator > ret;
ret = myMultimap.equal_range(it->first);
for(multimap <string, map <string, int> >::iterator it2 = ret.first; it2 != ret.second; it2++){
//here i just want to print map <string , int>
cout << (*it2).second.first << endl;
cout << (*it2).second.second << endl;
}
}
when i run it i get class std::map<std::basic_string<char>, int>’ don't have a member called ‘first’ and same thing for second.second. Sorry about my english is not my mother language.
Lets make things easier for ourselves to start with
typedef std::map<std::string, int> InnerMap;
typedef std::multimap<std::string, InnerMap> StringMap;
StringMap myMultimap;
Now, that outer loop
for (StringMap::iterator it = myMultimap.begin(); it != myMultimap.end(); ++it)
{
std::cout << "[" << it->first << "]:";
for (InnerMap::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
{
std::cout << " " << it2->first << ":" << it2->second;
}
std::cout << '\n';
}
We can also, if you have C++11, make things simpler by using auto
for (auto it = myMultimap.begin(); it != myMultimap.end(); ++it)
{
std::cout << "[" << it->first << "]:";
for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2)
{
std::cout << " " << it2->first << ":" << it2->second;
}
std::cout << '\n';
}
What we're doing:
for (StringMap::iterator it = myMultimap.begin(); it != myMultimap.end(); ++it)
This iterates across all of the std::pair<std::string /*key*/, InnerMap /*value*/> elements that actually make up the outer multimap. If you have one key twice, you'll see both entries.
it->first is the std::string key for the current multimap entry, it->second is the InnerMap value of the current entry.
for (InnerMap::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
This iterates over the std::pair<std::string, int> InnerMap elements of the map that is the value of this multimap slot.
--- EDIT ---
Ultimately, using C++11 you could use range based for (not sure why I thought this would be messier)
// use 'auto&' so we take a reference instead of a copy.
for (auto& it : myMultimap)
{
std::cout << "[" << it.first << "]:";
for (auto it2 : it.second)
{
std::cout << " " << it2.first << ":" << it2.second;
}
std::cout << '\n';
}
Note that, in this case, we now use "." instead of "->". This is because we're actually seeing every element (std::pair<...>) in the multimap/map, rather than a simple iterator. That is, it is of type std::pair<std::string, InnerMap>& and it2 is of type std::pair<std::string, int>&.
map<string, int>::iterator in;
for(multimap <string, map <string, int> >::iterator it = myMultimap.begin(); it != myMultimap.end(); it =myMultimap.upper_bound(it->first)){
pair< multimap <string,map <string, int> >::iterator , multimap <string,map <string, int> >::iterator > ret;
ret = myMultimap.equal_range(it->first);
for(multimap <string, map <string, int> >::iterator it2 = ret.first; it2 != ret.second; it2++){
//get the map with begin() and assign it to an iterator
in = it2->second.begin();
cout << in->first << " "<< in->second << endl;
}
}

Set of vectors in c++

How I can get the elements in the vectors set? This is the code I have :
std::set< std::vector<int> > conjunto;
std::vector<int> v0 = std::vector<int>(3);
v0[0]=0;
v0[1]=10;
v0[2]=20;
std::cout << v0[0];
conjunto.insert(v0);
v0[0]=1;
v0[1]=11;
v0[2]=22;
conjunto.insert(v0);
std::set< std::vector<int> >::iterator it;
std::cout << conjunto.size();
for( it = conjunto.begin(); it != conjunto.end(); it++)
std::cout << *it[0] ;
The [] operator takes precedence over the * operator, so you want to change the for loop to:
for (it = conjunto.begin(); it != conjunto.end(); it++)
std::cout << (*it)[0] << std::endl;
You're close. You need to pull the vector out of the set iterator. See below.
main()
{
std::set< std::vector<int> > conjunto;
std::vector<int> v0 = std::vector<int>(3);
v0[0]=0;
v0[1]=10;
v0[2]=20;
std::cout << v0[0] << endl;
conjunto.insert(v0);
v0[0]=1;
v0[1]=11;
v0[2]=22;
conjunto.insert(v0);
std::set< std::vector<int> >::iterator it;
std::cout << "size = " << conjunto.size() << endl;
for( it = conjunto.begin(); it != conjunto.end(); it++) {
const std::vector<int>& i = (*it); // HERE we get the vector
std::cout << i[0] << endl; // NOW we output the first item.
}
Output:
$ ./a.out
0
size = 2
0
1
Now, with C++11 standart, it's easier:
set< vector<int> > conjunto;
// filling conjunto ...
for (vector<int>& v: conjunto)
cout << v[0] << endl;
std::set<std::vector<int> >::const_iterator it = cunjunto.begin();
std::set<std::vector<int> >::const_iterator itEnd = conjunto.end();
for(; it != itEnd; ++it)
{
// Here *it references the element in the set (vector)
// Therefore, declare iterators to loop the vector and print it's elements.
std::vector<int>::const_iterator it2 = (*it).begin();
std::vector<int>::const_iterator it2End = (*it).end();
for (; it2 != it2End; ++it2)
std::cout << *it2;
}