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