Reputation: 447
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";
Upvotes: 1
Views: 2744
Reputation: 463
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";
}
}
Upvotes: 0
Reputation: 32852
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 value
s 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:
vec[index]
)std::vector< std::pair<int, std::string>>::const_iterator itr;
)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;
}
Upvotes: 2
Reputation: 1631
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";
}
}
Upvotes: 1
Reputation: 1161
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 ;)
Upvotes: 1