I have tried below code snippets to print map of map values but I could not able to access second map values.
#include <iostream>
#include <iterator>
#include <map>
#include <string>
using namespace std;
int main()
{
map< string, std::map<std::string, int> > someStorage;
//First key values
someStorage["key1"]["This Is Layer one"] = 100;
someStorage["Key1"]["This Is Layer Two"] = 120;
//second key, values
someStorage["key2"]["This Is Layer one"] = 110;
someStorage["key2"]["This Is Layer Two"] = 110;
map< string, std::map<std::string, int> > ::iterator itr;
cout << "\nThe map is : \n";
for (itr = someStorage.begin(); itr != someStorage.end(); ++itr)
{
cout << '\t' << itr->first;
//<< '\t' << (itr->second).first << '\n' <==problematic part
//<< '\t' << (itr->second).second << '\n'; <==problematic part
}
cout << endl;
return 0;
}
How to print/access these values and how do I differentiate "This Is Layer
one" for "key1" and "key2". Because I can see that it is getting
overwritten if we assign key2 value, key1 has same. Why?
Also I am expecting below key value pairs
Key1 => {This Is Layer one, 100}
{This Is Layer Two, 120}
Key2 =>{This Is Layer one, 110}
{This Is Layer Two, 110}
.
In addition to the other answers here, you can use structured binding (since c++17) to simplify this:
for (auto const& [key, val] : someStorage) { // val = second map
for (auto const& [k, v] : val) { // k = first, v = second
cout << key << ' ' << k << ' ' << v << '\n';
}
}
You need a second, inner loop to traverse the nested std::map. Like this:
for (auto itr = someStorage.cbegin(); itr != someStorage.cend(); ++itr)
{
cout << itr->first << " => ";
for (auto innerItr = itr->second.cbegin(); innerItr != itr->second.cend(); ++innerItr)
{
cout << innerItr->first << " : " << innerItr->second << " ";
}
cout << "\n";
}
Note that for the desired output, you need to capitalize the keys such that they are "Key1" and "Key2" (this is currently a typo in your question). Note further that I changed to begin/end member functions to cbegin/cend, as the loop doesn't modify the container.
You'll need to iterate over your inner map as well, something like:
for (auto itr1 = someStorage.begin(); itr1 != someStorage.end(); ++itr1)
{
cout << '\t' << itr->first << ":\n";
for (auto itr2 = itr1->second.begin(); itr2 != itr1->second.end(); ++itr2)
{
cout << "\t\t" << itr2->first << '\n';
cout << "\t\t" << itr2->second << '\n';
}
}
Thank you for the output. My Gcc version did not support auto iterate
for (itr1 = someStorage.begin(); itr1 != someStorage.end(); ++itr1)
{
cout << '\t' << itr1->first << ":\n";
std::map<std::string, int> ::iterator itr2;
for (itr2 = itr1->second.begin(); itr2 != itr1->second.end(); ++itr2)
{
cout << "\t\t" << itr2->first << '\n';
cout << "\t\t" << itr2->second << '\n';
}
}
Related
I am having a map like this
typedef vector< pair<int, string> > Categories;
map<string,Categories> cats;
but when I am trying to read elements of the map like
for(map<string,Categories>::const_iterator it = cats.begin(); it != cats.end(); ++it)
{
std::cout << it->first << " " << it->second.first<<"\n";
}
I do get errors
error: 'const class std::vector<std::pair<int, std::basic_string<char>
' has no member named 'first' std::cout << it->first << " " << it-> second.first<<"\n";
error: 'const class std::vector ' has no member named 'first'
std::cout << it->first << " " << it->second.first<<"\n";
Its clear as Crystal, that you might have many elements in your values of your map, which is a std::vector< std::pair<int, std::string>>
Then how would you print elements of a vector? The options are:
random access (i.e, vec[index])
iterator (i.e, std::vector< std::pair<int, std::string>>::const_iterator itr;)
or by a range based for loop (i.e, for(const auto& it: vec) )
In your case, if you wanna have something simple and easy code is using a range based loop:
for(const auto& it: cats)
{
std::cout << it.first << " = "; // keys
for(const auto& ve: it.second) // values vec
std::cout << ve.first << "-" << ve.second << "\t";
std::cout << std::endl;
}
If you still wanna have long iterator loops, here is it.
see live action here: https://www.ideone.com/3bS1kR
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <iterator>
typedef std::vector< std::pair<int, std::string>> Categories;
int main()
{
std::map<std::string, Categories> cats;
cats["key1"] = {std::make_pair(1, "pair1"), std::make_pair(1, "pair2"), std::make_pair(1, "par3")};
cats["key2"] = {std::make_pair(2, "pair1"), std::make_pair(2, "pair2")};
cats["key3"] = {std::make_pair(3, "pair1")};
std::cout << "Range based loop \n";
for(const auto& it: cats)
{
std::cout << it.first << " = "; // keys
for(const auto& ve: it.second) // values vec
std::cout << ve.first << "-" << ve.second << "\t";
std::cout << std::endl;
}
std::cout << "\nIterator loop \n";
std::map<std::string, Categories>::const_iterator it;
std::vector< std::pair<int, std::string>>::const_iterator curr_val_it;
for(it = cats.cbegin(); it != cats.cend(); ++it)
{
std::cout << it->first << " = "; // keys
for(curr_val_it = it->second.cbegin(); curr_val_it != it->second.cend(); ++curr_val_it )
std::cout << curr_val_it->first << "-" << curr_val_it->second << "\t"; // values vec
std::cout << std::endl;
}
return 0;
}
you need to access a element of the vector first, then the pair within.
... it->second[0].first<< ...
better impl of loop:
for(const auto& cat : cats)
{
string mapidx = cat.first;
vector<pair<int, std::string>> catvect = cat.second;
}
then you can have a seperate loop to read the contents of the vector:
for(const auto& cat : cats)
{
string mapidx = cat.first;
vector<pair<int, std::string>> catvect = cat.second;
for (const auto& entry : catvect)
{
int number = entry.first;
string whatever = entry.second;
}
}
the temp variables are just for readability, no need for all the copies ;)
Error is exacly what compiler told you:
const class std::vector ' has no member named 'first'
so, you have do decide how to print your map by overloading ostream opeartor, below example how it can be achived:
#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <vector>
typedef std::vector<std::pair<int, std::string>> Categories;
std::map<std::string,Categories> cats;
std::ostream& operator << (std::ostream& os, const std::vector<std::pair<int, std::string>>& v)
{
os << "[";
for (auto& el : v) {
os << " " << el.first << " : " << el.second;
}
os << "]";
return os;
}
int main() {
cats.emplace("cat1", std::vector<std::pair<int, std::string>>(1, std::make_pair(1, "category1")));
for(auto& cat : cats) {
std::cout << cat.first << " " << cat.second << "\n";
}
}
Since we are storing Vector Categories inside a Map we will have to iterate Vector too:
for(map<string,Categories>::const_iterator it = cats.begin(); it != cats.end(); ++it)
{
//iterator for vector (it->second)
for(Categories::const_iterator it2 = it->second.begin(); it2 != it->second.end(); it2++ )
{
std::cout << it->first << " " << it2->first<<" "<<it2->second <<"\n";
}
}
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;
}
I am trying to display the contents of a multimap with a string and a vector as key and value, respectively. I run into problems when I try to dislpay the contents of the vector (value in multimap). What I have done so far is:
multimap<string, vector<string> > someMultimap;
vector<string> someVector;
someVector.push_back("test");
someMultimap.insert(pair<string, vector<string> >("KEY", someVector));
//So for it works fine...
multimap <string, vector<string> >::iterator it;
for (it = someMultimap.begin(); it != someMultimap.end(); ++it)
{
cout << it->first << endl << endl << it->second << endl << endl;
^^^^^^^^^^
this is the problem, canĀ“t do this with a vector(?)
}
Does anyone have a suggestion for solving the problem?
You can add a second loop for the vector.
multimap <string, vector<string> >::const_iterator it;
for (it = someMultimap.begin(); it != someMultimap.end(); ++it)
{
cout << it->first << endl ;
vector<string>::const_iterator itVec;
for (itVec = it->second.begin(); itVec != it->second.end(); ++itVec)
{
cout << *itVec <<" ";
}
cout<<endl;
}
If you don't plan to modify any value you can make your iterators const
Use std::copy to output the vector's contents with a single function:
#include <iterator>
#include <algorithm>
#include <iostream>
//..
using namespace std;
for (it = someMultimap.begin(); it != someMultimap.end(); ++it)
{
cout << it->first << "\n\n";
copy(it->second.begin(), it->second.end(), ostream_iterator<string>(cout, " "));
cout << "\n\n";
}
Loop through the vector and print:
cout << it->first << endl << endl;
for (vector<string>::iterator j(it->second.begin()); j != it->second.end(); ++j)
cout << *j << " ";
cout << endl << endl;
Also, don't use std::endl, it flushes on each call which can hinder performance.
Well, you can define what it means to send a std::vector to a std::ostream.
Here's an example of one way to do it:
template<typename T>
std::ostream& operator <<(std::ostream& stream, std::vector<T> const& v) {
for (auto&& e : v) {
stream << e << ' ';
}
return stream;
}
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;
}
How can I print the contents of a nested map? I am counting the number of times a word appears in a file, reporting it by line number and number of times per line. The words, lines, and occurrences per line are being stored in the following container:
map<string, map<int, int>> tokens;
However, I'm not sure on the syntax. I am printing the outer map that lists all of the words using the following code, but can't figure out how to print the inner values (the line number and number of times the word appears on each line) as well. I assume I can just include it inline in the for loop, but I can't figure out how:
for (map <string, map<int, int>>::iterator it = tokens.begin(); it != tokens.end(); ++it){
cout << it->first << " : " << /* assume I can include another statement here to print the values? */ endl;
}
I am trying to get an output similar to this:
(word : line:occurrences, line:occurrences, ...)
about : 16:1, 29:1, 166:1, 190:1, 191:1
above : 137:1
accompanied : 6:1
across : 26:1
admit : 20:1
advancing : 170:1
.
.
.
It is actually pretty simple.
You just get the internal map with it->second, and you iterate through that the same way.
Thereby, you would write something like this:
for (map <string, map<int, int>>::iterator it = tokens.begin(); it != tokens.end(); ++it){
cout << it->first << " : ";
map<int, int> &internal_map = it->second;
for (map<int, int>::iterator it2 = internal_map.begin(); it2 != internal_map.end(); ++it2){
if (it2 != internal_map.begin())
cout << ",";
cout << it2->first << ":" << it2->second;
}
cout << endl;
}
You could write something like this if you have C++11 support:
for (auto it : tokens) {
cout << it->first << " : ";
map<int, int> &internal_map = it->second;
for (auto it2: internal_map) {
if (it2 != internal_map.begin())
cout << ",";
cout << it2->first << ":" << it2->second;
}
cout << endl;
}
C++17
Since C++17 you can use range-based for loops together with structured bindings for iterating over maps.
This way, the readability of lpapp's C++11 solution can be further improved as follows:
for (auto const &[k1, v1] : tokens) {
std::cout << k1 << " : ";
for (auto const &[k2, v2] : v1) {
if (&k2 != &v1.begin()->first)
std::cout << ", ";
std::cout << k2 << ":" << v2;
}
std::cout << std::endl;
}
Note: I admit, the check for printing a comma is a bit messy. If you are looking for a nicer solution, you
might want to take a look at this Q&A.
Code on Coliru
Since we are only printing the elements, not modifying it, I would make more use of const, (a) const reference and (b) const iterators.
Also, for pre-C++11, it helps to define typedef's for complex types.
#include <string>
#include <map>
#include <iostream>
using namespace std;
typedef map<int, int> InnerMap;
typedef map<string, InnerMap> OuterMap;
void printClassic( OuterMap const & tokens ) {
for( OuterMap::const_iterator cit = tokens.begin();
cit != tokens.end(); ++cit ) {
cout << cit->first << " : ";
InnerMap const & imap = cit->second;
for( InnerMap::const_iterator cit2 = imap.begin();
cit2 != imap.end(); ++cit2 ) {
cout << cit2->first << ":" << cit2->second << ",";
}
cout << endl;
}
}
void printCpp11( OuterMap const & tokens ) {
for( auto const & cit : tokens ) {
cout << cit.first << " : ";
auto const & imap = cit.second;
for( auto const & cit2 : imap ) {
cout << cit2.first << ":" << cit2.second << ",";
}
cout << endl;
}
}