Print multimap<string, vector<string>>? - c++

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;
}

Related

Could not print map of map value in C++

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';
}
}

How to read a map of <string,vector<pair<int, string>>>

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";
}
}

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 can I print the content of map<string, map<int, int>> to cout?

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;
}
}

How can I display the content of a map on the console?

I have a map declared as follows:
map < string , list < string > > mapex ; list< string > li;
How can I display the items stored in the above map on the console?
Update (Back to the future): with C++11 range-based for loops –
std::map<Key, Value> m { ... /* initialize it */ ... };
for (const auto &p : m) {
std::cout << "m[" << p.first << "] = " << p.second << '\n';
}
Well it depends on how you want to display them, but you can always iterate them easily:
typedef map<string, list<string>>::const_iterator MapIterator;
for (MapIterator iter = mapex.begin(); iter != mapex.end(); iter++)
{
cout << "Key: " << iter->first << endl << "Values:" << endl;
typedef list<string>::const_iterator ListIterator;
for (ListIterator list_iter = iter->second.begin(); list_iter != iter->second.end(); list_iter++)
cout << " " << *list_iter << endl;
}
I'd try the following
void dump_list(const std::list<string>& l) {
for ( std::list<string>::const_iterator it = l.begin(); l != l.end(); l++ ) {
cout << *l << endl;
}
}
void dump_map(const std::map<string, std::list<string>>& map) {
for ( std::map<string,std::list<string>>::const_iterator it = map.begin(); it != map.end(); it++) {
cout << "Key: " << it->first << endl;
cout << "Values" << endl;
dump_list(it->second);
}
I'm a little off topic here...
I guess you want to dump the map content for debugging. I like to mention that the next gdb release (version 7.0) will have a built in python interpreter which will be used by the gcc libstdc++ to provide stl pretty printers. Here is an example for your case
#include <map>
#include <map>
#include <list>
#include <string>
using namespace std;
int main()
{
typedef map<string, list<string> > map_type;
map_type mymap;
list<string> mylist;
mylist.push_back("item 1");
mylist.push_back("item 2");
mymap["foo"] = mylist;
mymap["bar"] = mylist;
return 0; // stopped here
}
which results in
(gdb) print mymap
$1 = std::map with 2 elements = {
["bar"] = std::list = {
[0] = "item 1",
[1] = "item 2"
},
["foo"] = std::list = {
[0] = "item 1",
[1] = "item 2"
}
}
Yay!
Another form, using <algorithm>:
void printPair(const pair<string, list<string> > &p)
{
cout << "Key: " << p.first << endl;
copy(p.second.begin(), p.second.end(), ostream_iterator<string>(cout, "\n"));
}
for_each(mapex.begin(), mapex.end(), printPair);
Test program:
#include <iostream>
#include <map>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
void printPair(const pair<string, list<string> > &p)
{
cout << "Key: " << p.first << endl;
copy(p.second.begin(), p.second.end(), ostream_iterator<string>(cout, "\n"));
}
int main()
{
map<string, list<string> > mapex;
list<string> mylist1;
mylist1.push_back("item 1");
mylist1.push_back("item 2");
mapex["foo"] = mylist1;
list<string> mylist2;
mylist2.push_back("item 3");
mylist2.push_back("item 4");
mylist2.push_back("item 5");
mapex["bar"] = mylist2;
for_each(mapex.begin(), mapex.end(), printPair);
}
You can write a quite generic overloaded function, which is good for two purposes:
It works with any map.
It allows for using <<.
The function is
template<class key_t, class value_t>
ostream& operator<<(ostream& os, const map<key_t, value_t>& m) {
for (typename map<key_t, value_t>::const_iterator it = m.begin();
it != m.end(); it++) {
os << "Key: " << it->first << ", Value: " << it->second;
}
return os;
}
cout << will work with any map for which << is defined for typenames key_t and value_t. In your case, this is not defined for value_t (= list<string>), so you also have to define it.
In a similar spirit, you can use
template<class T>
ostream& operator<<(ostream& os, const list<T>& l) {
for (typename list<T>::const_iterator it = l.begin(); it != l.end(); it++) {
os << "\"" << *it << "\", ";
}
return os;
}
So, you may:
Add these two functions.
Add the prototypes where needed.
Use using namespace std; (or add std:: as needed).
Use, e.g.,
cout << mapex << endl;
cout << li << endl;
Remember that if there is any other viable candidate for the <<s just defined (which I take there is not, otherwise you would likely not ask this question), it may take precedence over the present ones.
If you can use C++11 features, then I think range-based for loops as proposed in The Paramagnetic Croissant's answer provide the most readable option. However, if C++17 is available to you, then you can combine those loops with structured bindings to further increase readability, because you no longer need to use the first and second members. For your specific use case, my solution would look as follows:
std::map<std::string, std::list<std::string>> mapex;
mapex["a"] = { "1", "2", "3", "4" };
mapex["b"] = { "5", "6", "7" };
for (const auto &[k, v] : mapex) {
std::cout << "m[" << k.c_str() << "] =";
for (const auto &s : v)
std::cout << " " << s.c_str();
std::cout << std::endl;
}
Output:
m[a] = 1 2 3 4
m[b] = 5 6 7
Code on Coliru