How can I loop through a C++ map of maps? - c++

How can I loop through a std::map in C++? My map is defined as:
std::map< std::string, std::map<std::string, std::string> >
For example, the above container holds data like this:
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
How can I loop through this map and access the various values?

Old question but the remaining answers are outdated as of C++11 - you can use a ranged based for loop and simply do:
std::map<std::string, std::map<std::string, std::string>> mymap;
for(auto const &ent1 : mymap) {
// ent1.first is the first key
for(auto const &ent2 : ent1.second) {
// ent2.first is the second key
// ent2.second is the data
}
}
this should be much cleaner than the earlier versions, and avoids unnecessary copies.
Some favour replacing the comments with explicit definitions of reference variables (which get optimised away if unused):
for(auto const &ent1 : mymap) {
auto const &outer_key = ent1.first;
auto const &inner_map = ent1.second;
for(auto const &ent2 : inner_map) {
auto const &inner_key = ent2.first;
auto const &inner_value = ent2.second;
}
}

You can use an iterator.
typedef std::map<std::string, std::map<std::string, std::string>>::iterator it_type;
for(it_type iterator = m.begin(); iterator != m.end(); iterator++) {
// iterator->first = key
// iterator->second = value
// Repeat if you also want to iterate through the second map.
}

for(std::map<std::string, std::map<std::string, std::string> >::iterator outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
for(std::map<std::string, std::string>::iterator inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
std::cout << inner_iter->second << std::endl;
}
}
or nicer in C++0x:
for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
for(auto inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
std::cout << inner_iter->second << std::endl;
}
}

With C++17 (or later), you can use the "structured bindings" feature, which lets you define multiple variables, with different names, using a single tuple/pair. Example:
for (const auto& [name, description] : planet_descriptions) {
std::cout << "Planet " << name << ":\n" << description << "\n\n";
}
The original proposal (by luminaries Bjarne Stroustrup, Herb Sutter and Gabriel Dos Reis) is fun to read (and the suggested syntax is more intuitive IMHO); there's also the proposed wording for the standard which is boring to read but is closer to what will actually go in.

Do something like this:
typedef std::map<std::string, std::string> InnerMap;
typedef std::map<std::string, InnerMap> OuterMap;
Outermap mm;
...//set the initial values
for (OuterMap::iterator i = mm.begin(); i != mm.end(); ++i) {
InnerMap &im = i->second;
for (InnerMap::iterator ii = im.begin(); ii != im.end(); ++ii) {
std::cout << "map["
<< i->first
<< "]["
<< ii->first
<< "] ="
<< ii->second
<< '\n';
}
}

C++11:
std::map< std::string, std::map<std::string, std::string> > m;
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
for (auto i : m)
for (auto j : i.second)
cout << i.first.c_str() << ":" << j.first.c_str() << ":" << j.second.c_str() << endl;
output:
name1:value1:data1
name1:value2:data2
name2:value1:data1
name2:value2:data2
name3:value1:data1
name3:value2:data2

As einpoklum mentioned in their answer, since C++17 you can also use structured binding declarations. I want to extend on that by providing a full solution for iterating over a map of maps in a comfortable way:
int main() {
std::map<std::string, std::map<std::string, std::string>> m {
{"name1", {{"value1", "data1"}, {"value2", "data2"}}},
{"name2", {{"value1", "data1"}, {"value2", "data2"}}},
{"name3", {{"value1", "data1"}, {"value2", "data2"}}}
};
for (const auto& [k1, v1] : m)
for (const auto& [k2, v2] : v1)
std::cout << "m[" << k1 << "][" << k2 << "]=" << v2 << std::endl;
return 0;
}
Output:
m[name1][value1]=data1
m[name1][value2]=data2
m[name2][value1]=data1
m[name2][value2]=data2
m[name3][value1]=data1
m[name3][value2]=data2
Note 1: For filling the map, I used an initializer list (which is a C++11 feature). This can sometimes be handy to keep fixed initializations compact.
Note 2: If you want to modify the map m within the loops, you have to remove the const keywords.
Code on Coliru

use std::map< std::string, std::map<std::string, std::string> >::const_iterator when map is const.

First solution is Use range_based for loop, like:
Note: When range_expression’s type is std::map then a range_declaration’s type is std::pair.
for ( range_declaration : range_expression )
//loop_statement
Code 1:
typedef std::map<std::string, std::map<std::string, std::string>> StringToStringMap;
StringToStringMap my_map;
for(const auto &pair1 : my_map)
{
// Type of pair1 is std::pair<std::string, std::map<std::string, std::string>>
// pair1.first point to std::string (first key)
// pair1.second point to std::map<std::string, std::string> (inner map)
for(const auto &pair2 : pair1.second)
{
// pair2.first is the second(inner) key
// pair2.second is the value
}
}
The Second Solution:
Code 2
typedef std::map<std::string, std::string> StringMap;
typedef std::map<std::string, StringMap> StringToStringMap;
StringToStringMap my_map;
for(StringToStringMap::iterator it1 = my_map.begin(); it1 != my_map.end(); it1++)
{
// it1->first point to first key
// it2->second point to inner map
for(StringMap::iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
{
// it2->second point to value
// it2->first point to second(inner) key
}
}

Related

C++ inserting into a map<double, multimap<int, Object*>>

How does one insert into a map<double, multimap<int, Object*> >?
I tried mymap.insert(make_pair(double, make_pair(int, Object*)));. Furthermore how do you access the Object* when iterating through it?
I tried it->second->second.
You seem to be wanting:
using MyMap = std::map<double, std::multimap<int, Object*> >;
MyMap mymap;
mymap.insert(std::make_pair(dbl, std::multimap<int, Object*>());
To enumerate:
#include <iostream>
#include <map>
struct Object {};
int main()
{
using MyMap = std::map<double, std::multimap<int, Object*> >;
MyMap mymap;
auto ins = mymap.insert(std::make_pair(42.0, std::multimap<int, Object*>()));
Object obj1, obj2;
ins.first->second.insert(std::make_pair(7, &obj1));
ins.first->second.insert(std::make_pair(7, &obj2));
for (auto const& pr : mymap)
{
std::cout << "dblkey: " << pr.first << '\n';
for (auto const& pr2 : pr.second)
{
std::cout << "\tintkey: "<< pr2.first
<< ", value: " << static_cast<const void*>(pr2.second) << '\n';
}
}
}
Output (pointer values vary, obviously)
dblkey: 42
intkey: 7, value: 0x7fff5fbff160
intkey: 7, value: 0x7fff5fbff158
In the end, your problem was a type issue more than anything else. You were attempting to insert a std::pair<int, Object*> where a std::multimap<int, Object*> instance belonged.
In a std::map<double, std::multimap<int, Object*> >, the second value is a single std::multimap object, but you are trying to set it to a std::pair object instead. std::multimap does not have a constructor that accepts a std::pair as input, which is why your code fails.
You need to construct a std::multimap object to insert into the std::map, eg:
double d = ...;
int i = ...;
Object *obj = ...;
std::multimap mm;
mm.insert(std::make_pair(i, obj));
mymap.insert(std::make_pair(d, mm));
Or:
mymap[d].insert(std::make_pair(i, obj));
When iterating the std::map, it will return an iterator to a std::pair where ->first is double and ->second is std::multimap<int, Object*>.
When iterating the std::multimap, it will return an iterator to a std::pair where ->first is int and ->second is Object*.
auto iter1 = mymap.begin;
while (iter1 != mymap.end())
{
auto &mm = iter1->second; // mm = std::multimap<int, Object*>
auto iter2 = mm.begin();
while (iter2 != mm.end())
{
auto obj = iter2->second; // obj = Object*
// use obj as needed...
++iter2;
}
++iter1;
}
This would be simpler if you used a ranged-based for loop instead:
for (auto &v1: mymap) // v1 = std::pair<double, std::multimap<int, Object*> >
{
auto &mm = v1.second; // mm = std::multimap<int, Object*>
for (auto &v2: mm) // v2 = std::pair<int, Object*>
{
auto obj = v2.second; // obj = Object*
// use obj as needed...
}
}

Check size in difficult map [duplicate]

How can I loop through a std::map in C++? My map is defined as:
std::map< std::string, std::map<std::string, std::string> >
For example, the above container holds data like this:
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
How can I loop through this map and access the various values?
Old question but the remaining answers are outdated as of C++11 - you can use a ranged based for loop and simply do:
std::map<std::string, std::map<std::string, std::string>> mymap;
for(auto const &ent1 : mymap) {
// ent1.first is the first key
for(auto const &ent2 : ent1.second) {
// ent2.first is the second key
// ent2.second is the data
}
}
this should be much cleaner than the earlier versions, and avoids unnecessary copies.
Some favour replacing the comments with explicit definitions of reference variables (which get optimised away if unused):
for(auto const &ent1 : mymap) {
auto const &outer_key = ent1.first;
auto const &inner_map = ent1.second;
for(auto const &ent2 : inner_map) {
auto const &inner_key = ent2.first;
auto const &inner_value = ent2.second;
}
}
You can use an iterator.
typedef std::map<std::string, std::map<std::string, std::string>>::iterator it_type;
for(it_type iterator = m.begin(); iterator != m.end(); iterator++) {
// iterator->first = key
// iterator->second = value
// Repeat if you also want to iterate through the second map.
}
for(std::map<std::string, std::map<std::string, std::string> >::iterator outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
for(std::map<std::string, std::string>::iterator inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
std::cout << inner_iter->second << std::endl;
}
}
or nicer in C++0x:
for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
for(auto inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
std::cout << inner_iter->second << std::endl;
}
}
With C++17 (or later), you can use the "structured bindings" feature, which lets you define multiple variables, with different names, using a single tuple/pair. Example:
for (const auto& [name, description] : planet_descriptions) {
std::cout << "Planet " << name << ":\n" << description << "\n\n";
}
The original proposal (by luminaries Bjarne Stroustrup, Herb Sutter and Gabriel Dos Reis) is fun to read (and the suggested syntax is more intuitive IMHO); there's also the proposed wording for the standard which is boring to read but is closer to what will actually go in.
Do something like this:
typedef std::map<std::string, std::string> InnerMap;
typedef std::map<std::string, InnerMap> OuterMap;
Outermap mm;
...//set the initial values
for (OuterMap::iterator i = mm.begin(); i != mm.end(); ++i) {
InnerMap &im = i->second;
for (InnerMap::iterator ii = im.begin(); ii != im.end(); ++ii) {
std::cout << "map["
<< i->first
<< "]["
<< ii->first
<< "] ="
<< ii->second
<< '\n';
}
}
C++11:
std::map< std::string, std::map<std::string, std::string> > m;
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
for (auto i : m)
for (auto j : i.second)
cout << i.first.c_str() << ":" << j.first.c_str() << ":" << j.second.c_str() << endl;
output:
name1:value1:data1
name1:value2:data2
name2:value1:data1
name2:value2:data2
name3:value1:data1
name3:value2:data2
As einpoklum mentioned in their answer, since C++17 you can also use structured binding declarations. I want to extend on that by providing a full solution for iterating over a map of maps in a comfortable way:
int main() {
std::map<std::string, std::map<std::string, std::string>> m {
{"name1", {{"value1", "data1"}, {"value2", "data2"}}},
{"name2", {{"value1", "data1"}, {"value2", "data2"}}},
{"name3", {{"value1", "data1"}, {"value2", "data2"}}}
};
for (const auto& [k1, v1] : m)
for (const auto& [k2, v2] : v1)
std::cout << "m[" << k1 << "][" << k2 << "]=" << v2 << std::endl;
return 0;
}
Output:
m[name1][value1]=data1
m[name1][value2]=data2
m[name2][value1]=data1
m[name2][value2]=data2
m[name3][value1]=data1
m[name3][value2]=data2
Note 1: For filling the map, I used an initializer list (which is a C++11 feature). This can sometimes be handy to keep fixed initializations compact.
Note 2: If you want to modify the map m within the loops, you have to remove the const keywords.
Code on Coliru
use std::map< std::string, std::map<std::string, std::string> >::const_iterator when map is const.
First solution is Use range_based for loop, like:
Note: When range_expression’s type is std::map then a range_declaration’s type is std::pair.
for ( range_declaration : range_expression )
//loop_statement
Code 1:
typedef std::map<std::string, std::map<std::string, std::string>> StringToStringMap;
StringToStringMap my_map;
for(const auto &pair1 : my_map)
{
// Type of pair1 is std::pair<std::string, std::map<std::string, std::string>>
// pair1.first point to std::string (first key)
// pair1.second point to std::map<std::string, std::string> (inner map)
for(const auto &pair2 : pair1.second)
{
// pair2.first is the second(inner) key
// pair2.second is the value
}
}
The Second Solution:
Code 2
typedef std::map<std::string, std::string> StringMap;
typedef std::map<std::string, StringMap> StringToStringMap;
StringToStringMap my_map;
for(StringToStringMap::iterator it1 = my_map.begin(); it1 != my_map.end(); it1++)
{
// it1->first point to first key
// it2->second point to inner map
for(StringMap::iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
{
// it2->second point to value
// it2->first point to second(inner) key
}
}

how to iterate through a map and print its contents in order C++ [duplicate]

How can I loop through a std::map in C++? My map is defined as:
std::map< std::string, std::map<std::string, std::string> >
For example, the above container holds data like this:
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
How can I loop through this map and access the various values?
Old question but the remaining answers are outdated as of C++11 - you can use a ranged based for loop and simply do:
std::map<std::string, std::map<std::string, std::string>> mymap;
for(auto const &ent1 : mymap) {
// ent1.first is the first key
for(auto const &ent2 : ent1.second) {
// ent2.first is the second key
// ent2.second is the data
}
}
this should be much cleaner than the earlier versions, and avoids unnecessary copies.
Some favour replacing the comments with explicit definitions of reference variables (which get optimised away if unused):
for(auto const &ent1 : mymap) {
auto const &outer_key = ent1.first;
auto const &inner_map = ent1.second;
for(auto const &ent2 : inner_map) {
auto const &inner_key = ent2.first;
auto const &inner_value = ent2.second;
}
}
You can use an iterator.
typedef std::map<std::string, std::map<std::string, std::string>>::iterator it_type;
for(it_type iterator = m.begin(); iterator != m.end(); iterator++) {
// iterator->first = key
// iterator->second = value
// Repeat if you also want to iterate through the second map.
}
for(std::map<std::string, std::map<std::string, std::string> >::iterator outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
for(std::map<std::string, std::string>::iterator inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
std::cout << inner_iter->second << std::endl;
}
}
or nicer in C++0x:
for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
for(auto inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
std::cout << inner_iter->second << std::endl;
}
}
With C++17 (or later), you can use the "structured bindings" feature, which lets you define multiple variables, with different names, using a single tuple/pair. Example:
for (const auto& [name, description] : planet_descriptions) {
std::cout << "Planet " << name << ":\n" << description << "\n\n";
}
The original proposal (by luminaries Bjarne Stroustrup, Herb Sutter and Gabriel Dos Reis) is fun to read (and the suggested syntax is more intuitive IMHO); there's also the proposed wording for the standard which is boring to read but is closer to what will actually go in.
Do something like this:
typedef std::map<std::string, std::string> InnerMap;
typedef std::map<std::string, InnerMap> OuterMap;
Outermap mm;
...//set the initial values
for (OuterMap::iterator i = mm.begin(); i != mm.end(); ++i) {
InnerMap &im = i->second;
for (InnerMap::iterator ii = im.begin(); ii != im.end(); ++ii) {
std::cout << "map["
<< i->first
<< "]["
<< ii->first
<< "] ="
<< ii->second
<< '\n';
}
}
C++11:
std::map< std::string, std::map<std::string, std::string> > m;
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
for (auto i : m)
for (auto j : i.second)
cout << i.first.c_str() << ":" << j.first.c_str() << ":" << j.second.c_str() << endl;
output:
name1:value1:data1
name1:value2:data2
name2:value1:data1
name2:value2:data2
name3:value1:data1
name3:value2:data2
As einpoklum mentioned in their answer, since C++17 you can also use structured binding declarations. I want to extend on that by providing a full solution for iterating over a map of maps in a comfortable way:
int main() {
std::map<std::string, std::map<std::string, std::string>> m {
{"name1", {{"value1", "data1"}, {"value2", "data2"}}},
{"name2", {{"value1", "data1"}, {"value2", "data2"}}},
{"name3", {{"value1", "data1"}, {"value2", "data2"}}}
};
for (const auto& [k1, v1] : m)
for (const auto& [k2, v2] : v1)
std::cout << "m[" << k1 << "][" << k2 << "]=" << v2 << std::endl;
return 0;
}
Output:
m[name1][value1]=data1
m[name1][value2]=data2
m[name2][value1]=data1
m[name2][value2]=data2
m[name3][value1]=data1
m[name3][value2]=data2
Note 1: For filling the map, I used an initializer list (which is a C++11 feature). This can sometimes be handy to keep fixed initializations compact.
Note 2: If you want to modify the map m within the loops, you have to remove the const keywords.
Code on Coliru
use std::map< std::string, std::map<std::string, std::string> >::const_iterator when map is const.
First solution is Use range_based for loop, like:
Note: When range_expression’s type is std::map then a range_declaration’s type is std::pair.
for ( range_declaration : range_expression )
//loop_statement
Code 1:
typedef std::map<std::string, std::map<std::string, std::string>> StringToStringMap;
StringToStringMap my_map;
for(const auto &pair1 : my_map)
{
// Type of pair1 is std::pair<std::string, std::map<std::string, std::string>>
// pair1.first point to std::string (first key)
// pair1.second point to std::map<std::string, std::string> (inner map)
for(const auto &pair2 : pair1.second)
{
// pair2.first is the second(inner) key
// pair2.second is the value
}
}
The Second Solution:
Code 2
typedef std::map<std::string, std::string> StringMap;
typedef std::map<std::string, StringMap> StringToStringMap;
StringToStringMap my_map;
for(StringToStringMap::iterator it1 = my_map.begin(); it1 != my_map.end(); it1++)
{
// it1->first point to first key
// it2->second point to inner map
for(StringMap::iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
{
// it2->second point to value
// it2->first point to second(inner) key
}
}

How to display map elements? [duplicate]

How can I loop through a std::map in C++? My map is defined as:
std::map< std::string, std::map<std::string, std::string> >
For example, the above container holds data like this:
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
How can I loop through this map and access the various values?
Old question but the remaining answers are outdated as of C++11 - you can use a ranged based for loop and simply do:
std::map<std::string, std::map<std::string, std::string>> mymap;
for(auto const &ent1 : mymap) {
// ent1.first is the first key
for(auto const &ent2 : ent1.second) {
// ent2.first is the second key
// ent2.second is the data
}
}
this should be much cleaner than the earlier versions, and avoids unnecessary copies.
Some favour replacing the comments with explicit definitions of reference variables (which get optimised away if unused):
for(auto const &ent1 : mymap) {
auto const &outer_key = ent1.first;
auto const &inner_map = ent1.second;
for(auto const &ent2 : inner_map) {
auto const &inner_key = ent2.first;
auto const &inner_value = ent2.second;
}
}
You can use an iterator.
typedef std::map<std::string, std::map<std::string, std::string>>::iterator it_type;
for(it_type iterator = m.begin(); iterator != m.end(); iterator++) {
// iterator->first = key
// iterator->second = value
// Repeat if you also want to iterate through the second map.
}
for(std::map<std::string, std::map<std::string, std::string> >::iterator outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
for(std::map<std::string, std::string>::iterator inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
std::cout << inner_iter->second << std::endl;
}
}
or nicer in C++0x:
for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
for(auto inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
std::cout << inner_iter->second << std::endl;
}
}
With C++17 (or later), you can use the "structured bindings" feature, which lets you define multiple variables, with different names, using a single tuple/pair. Example:
for (const auto& [name, description] : planet_descriptions) {
std::cout << "Planet " << name << ":\n" << description << "\n\n";
}
The original proposal (by luminaries Bjarne Stroustrup, Herb Sutter and Gabriel Dos Reis) is fun to read (and the suggested syntax is more intuitive IMHO); there's also the proposed wording for the standard which is boring to read but is closer to what will actually go in.
Do something like this:
typedef std::map<std::string, std::string> InnerMap;
typedef std::map<std::string, InnerMap> OuterMap;
Outermap mm;
...//set the initial values
for (OuterMap::iterator i = mm.begin(); i != mm.end(); ++i) {
InnerMap &im = i->second;
for (InnerMap::iterator ii = im.begin(); ii != im.end(); ++ii) {
std::cout << "map["
<< i->first
<< "]["
<< ii->first
<< "] ="
<< ii->second
<< '\n';
}
}
C++11:
std::map< std::string, std::map<std::string, std::string> > m;
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
for (auto i : m)
for (auto j : i.second)
cout << i.first.c_str() << ":" << j.first.c_str() << ":" << j.second.c_str() << endl;
output:
name1:value1:data1
name1:value2:data2
name2:value1:data1
name2:value2:data2
name3:value1:data1
name3:value2:data2
As einpoklum mentioned in their answer, since C++17 you can also use structured binding declarations. I want to extend on that by providing a full solution for iterating over a map of maps in a comfortable way:
int main() {
std::map<std::string, std::map<std::string, std::string>> m {
{"name1", {{"value1", "data1"}, {"value2", "data2"}}},
{"name2", {{"value1", "data1"}, {"value2", "data2"}}},
{"name3", {{"value1", "data1"}, {"value2", "data2"}}}
};
for (const auto& [k1, v1] : m)
for (const auto& [k2, v2] : v1)
std::cout << "m[" << k1 << "][" << k2 << "]=" << v2 << std::endl;
return 0;
}
Output:
m[name1][value1]=data1
m[name1][value2]=data2
m[name2][value1]=data1
m[name2][value2]=data2
m[name3][value1]=data1
m[name3][value2]=data2
Note 1: For filling the map, I used an initializer list (which is a C++11 feature). This can sometimes be handy to keep fixed initializations compact.
Note 2: If you want to modify the map m within the loops, you have to remove the const keywords.
Code on Coliru
use std::map< std::string, std::map<std::string, std::string> >::const_iterator when map is const.
First solution is Use range_based for loop, like:
Note: When range_expression’s type is std::map then a range_declaration’s type is std::pair.
for ( range_declaration : range_expression )
//loop_statement
Code 1:
typedef std::map<std::string, std::map<std::string, std::string>> StringToStringMap;
StringToStringMap my_map;
for(const auto &pair1 : my_map)
{
// Type of pair1 is std::pair<std::string, std::map<std::string, std::string>>
// pair1.first point to std::string (first key)
// pair1.second point to std::map<std::string, std::string> (inner map)
for(const auto &pair2 : pair1.second)
{
// pair2.first is the second(inner) key
// pair2.second is the value
}
}
The Second Solution:
Code 2
typedef std::map<std::string, std::string> StringMap;
typedef std::map<std::string, StringMap> StringToStringMap;
StringToStringMap my_map;
for(StringToStringMap::iterator it1 = my_map.begin(); it1 != my_map.end(); it1++)
{
// it1->first point to first key
// it2->second point to inner map
for(StringMap::iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
{
// it2->second point to value
// it2->first point to second(inner) key
}
}

How do I convert values from a vector to a map in c++?

I want to do something like this. Is there a stl algorithm that does this easily?
for each(auto aValue in aVector)
{
aMap[aValue] = 1;
}
If you have a vector of pairs, where the first item in the pair will be the key for the map, and the second item will be the value associated with that key, you can just copy the data to the map with an insert iterator:
std::vector<std::pair<std::string, int> > values {
{"Jerry", 1},
{ "Jim", 2},
{ "Bill", 3} };
std::map<std::string, int> mapped_values;
std::copy(values.begin(), values.end(),
std::inserter(mapped_values, mapped_values.begin()));
or, you could initialize the map from the vector:
std::map<std::string, int> m2((values.begin()), values.end());
Maybe like this:
std::vector<T> v; // populate this
std::map<T, int> m;
for (auto const & x : v) { m[x] = 1; }
You might std::transform the std::vector into a std::map
std::vector<std::string> v{"I", "want", "to", "do", "something", "like", "this"};
std::map<std::string, int> m;
std::transform(v.begin(), v.end(), std::inserter(m, m.end()),
[](const std::string &s) { return std::make_pair(s, 1); });
This creates std::pairs from the vector's elements, which in turn are inserted into the map.
Or, as suggested by #BenFulton, zipping two vectors into a map
std::vector<std::string> k{"I", "want", "to", "do", "something", "like", "this"};
std::vector<int> v{1, 2, 3, 4, 5, 6, 7};
std::map<std::string, int> m;
auto zip = [](const std::string &s, int i) { return std::make_pair(s, i); };
std::transform(k.begin(), k.end(), v.begin(), std::inserter(m, m.end()), zip);
Assuming items in vector are related in order, maybe this example can help :
#include <map>
#include <vector>
#include <string>
#include <iostream>
std::map<std::string, std::string> convert_to_map(const std::vector<std::string>& vec)
{
std::map<std::string, std::string> mp;
std::pair<std::string, std::string> par;
for(unsigned int i=0; i<vec.size(); i++)
{
if(i == 0 || i%2 == 0)
{
par.first = vec.at(i);
par.second = std::string();
if(i == (vec.size()-1))
{
mp.insert(par);
}
}
else
{
par.second = vec.at(i);
mp.insert(par);
}
}
return mp;
}
int main(int argc, char** argv)
{
std::vector<std::string> vec;
vec.push_back("customer_id");
vec.push_back("1");
vec.push_back("shop_id");
vec.push_back("2");
vec.push_back("state_id");
vec.push_back("3");
vec.push_back("city_id");
// convert vector to map
std::map<std::string, std::string> mp = convert_to_map(vec);
// print content:
for (auto it = mp.cbegin(); it != mp.cend(); ++it)
std::cout << " [" << (*it).first << ':' << (*it).second << ']';
std::cout << std::endl;
return 0;
}
A very generic approach to this, since you didn't specify any types, can be done as follows:
template<class Iterator, class KeySelectorFunc,
class Value = std::decay_t<decltype(*std::declval<Iterator>())>,
class Key = std::decay_t<decltype(std::declval<KeySelectorFunc>()(std::declval<Value>()))>>
std::map<Key, Value> toMap(Iterator begin, Iterator end, KeySelectorFunc selector) {
std::map<Key, Value> map;
std::transform(begin, end, std::inserter(map, map.end()), [selector](const Value& value) mutable {
return std::make_pair(selector(value), value);
});
return map;
}
Usage:
struct TestStruct {
int id;
std::string s;
};
std::vector<TestStruct> testStruct = {
TestStruct{1, "Hello"},
TestStruct{2, "Hello"},
TestStruct{3, "Hello"}
};
std::map<int, TestStruct> map = toMap(testStruct.begin(), testStruct.end(),
[](const TestStruct& t) {
return t.id;
}
);
for (const auto& pair : map) {
std::cout << pair.first << ' ' << pair.second.id << ' ' << pair.second.s << '\n';
}
// yields:
// 1 1 Hello
// 2 2 Hello
// 3 3 Hello
The parameter selector function is used to select what to use for the key in the std::map.
Try this:
for (auto it = vector.begin(); it != vector.end(); it++) {
aMap[aLabel] = it;
//Change aLabel here if you need to
//Or you could aMap[it] = 1 depending on what you really want.
}
I assume this is what you are trying to do.
If you want to update the value of aLabel, you could change it in the loop. Also, I look back at the original question, and it was unclear what they wanted so I added another version.
Yet another way:
#include <map>
#include <vector>
#include <boost/iterator/transform_iterator.hpp>
int main() {
using T = double;
std::vector<T> v;
auto f = [](T value) { return std::make_pair(value, 1); };
std::map<T, int> m(boost::make_transform_iterator(v.begin(), f),
boost::make_transform_iterator(v.end(), f));
}
But I don't think it beats range-for loop here in terms of readability and execution speed.
For converting values of a array or a vector directly to map we can do like.
map<int, int> mp;
for (int i = 0; i < m; i++)
mp[a[i]]++;
where a[i] is that array we have with us.