I have a stacked map that looks like this:
std::multimap <double, std::map<int,TypeA> > m
How can I point to the value of TypeA? I have tried:
TypeA t = m.second.second
or pointer:
for (std::multimap <double, std::map<int,StopID>>::iterator p = m.begin(); p != m.end(); p ++ ){
....
TypeA t = p->second->second
}
However, I got this error
no member named second in std::map...
Any idea?
for (std::multimap <double, std::map<int,StopID>>::iterator p = m.begin(); p != m.end(); p ++ ){
In the above you are iterating over the multimap and p->second points at the whole inner map, not a single entry in it. You need to iterate over the map too to access all entries in that.
You can use range based for-loops and structured bindings to make life easier.
for(auto& [the_double, the_map] : m) {
for(auto& [the_int, the_type_a] : the_map) {
// do what you want with the TypeA reference "the_type_a"
}
}
Edit: If I understand comments correctly, the map always contains exactly one int, TypeA pair - and in that case, just replace the map with a std::pair<int, TypeA> and you can have one loop only:
#include <utility> // std::pair
int main() {
std::multimap <double, std::pair<int, TypeA>> m;
for(auto& [the_double, the_pair] : m) {
auto& [the_int, the_type_a] = the_pair;
// do what you want with the int and TypeA references
}
}
m->second is a std::map object. You must use a loop for the next map:
using multimap_t = std::multimap <double, std::map<int, TypeA>>;
for (multimap_t::iterator p = m.begin(); p != m.end(); p++) {
std::map<int, TypeA>>& map = p->second;
for (decltype(p->second)::iterator miter = map.begin(); miter != map.end(); ++miter) {
TypeA t = miter->second;
// ...
}
}
A simpler version with auto (C++11):
for (auto p = m.begin(); p != m.end(); p++) {
auto& map = p->second;
for (auto miter = map.begin(); miter != map.end(); ++miter) {
TypeA t = miter->second;
// ...
}
}
Related
map <int, map<int, string>> DP;
if( DP.find( ? ) != DP.end() )
{
// have found
}
How to fill in (). It seem like two dimension. I know how to deal with one dimension, for example:
map<int, string> DP;
if( DP.find(1) != DP.end() )
{
// have found
}
But I don't know how to deal with two dimension.
One dimension at a time:
auto it1 = DP.find(1);
if (it1 != DP.end()) {
auto it2 = it1->find(2);
if (it2 != it1->end()) {
// found: it2->second
}
}
I think Kerrek SB`s codes exists a little problem. The way of visiting second(inner) dimension should be like this:
auto OuterIter = DP.find(1);
if (OuterIter != DP.end())
{
auto InnerMap = OuterIter->second;
auto InnerIter = InnerMap.find(0);
if (InnerIter != InnerMap.end())
{
// found the second(inner) dimension element
}
}
And you can think about chtz`s advise: You may also consider directly using std::map, std::string>
How to iterate through a std::map<string,int> and std::vector<int> using single for loop ?
I have seen this questions but could not solve my problem.
I am trying like this
map<string,int> data;
data["Shravan"] = 1;
data["Mama"] = 2;
data["Sa1"] = 3;
data["Jhandu"] = 4;
vector<int> values = {1,2,3,4};
for(const auto& it1: data,it2 : values) {
// Do something
}
Edit : I can not go through one by one. Because i am using the key of std::map and value of std::vector in the same function. Which will be called inside for loop.
Both the container of same size.
If you know there's both the same length, use something like:
auto vit = begin(value);
auto mit = begin(data);
for (; vit != end(value); ++mit, ++vit) {
// Use mit and vit
}
How about a do-while? Provided that your containers aren't empty.
auto iv = std::begin(value);
auto id = std::begin(data);
do {
// Use those iterators
} while(++iv != std::end(value) && ++id != std::end(data))
Or use while if you'd like to handle empty containers too.
auto iv = std::begin(value);
auto id = std::begin(data);
while(iv != std::end(value) && id != std::end(data)) {
// Use those iterators
iv++; id++;
}
Consider boost::zip_iterator discussed in this answer https://stackoverflow.com/a/8513803/2210478
You can iterate over both the map and the vector and make sure to check the iterators against the end of the corresponding container.
auto map_iter = data.begin();
auto vec_iter = value.begin();
for (; map_iter != data.end() && vec_iter != value.end();
++map_iter, ++vec_iter) {
// Use map_iter and vec_iter
}
I am creating a function that recursively finds structs within structs.
I create a list < list <struct> > and then I call a function that finds the first list <struct> and pushes it to the back of a list. I need to iterate through that list of structs and look for more structs within.
Here is my code, this may make things more clear.
std::list<std::list<iof_chunk>> read_ALLChunks (iof_chunk* reading_material)
{
std::list< std::list<iof_chunk> > ALL_CHUNKS;
std::list< std::list<iof_chunk> >::iterator iter;
if ( ((*reading_material).header.BASEID_Code != 'BODY') && (checkfor_header( &(*reading_material).data[20] )) )
{
ALL_CHUNKS.push_back( read_subChunks(reading_material) );
for( int i = 0; i < ALL_CHUNKS.size; ++i)
{
}
}
}
My Question about the code above: How do I access an iof_chunk in ALL_CHUNKS
You can use iterator in this way:
std::list< std::list<iof_chunk> > ALL_CHUNKS;
std::list< std::list<iof_chunk> >::iterator i = ALL_CHUNKS.begin();
std::list<iof_chunk> one_chunk;
for(; i != ALL_CHUNKS.end(); ++i) {
*i = one_chunk;
/* it's just an example */
}
edit
std::list< std::list<iof_chunk> > ALL_CHUNKS;
std::list< std::list<iof_chunk> >::iterator i = ALL_CHUNKS.begin();
for(; i != ALL_CHUNKS.end(); ++i) {
std::list<iof_chunk> i-th_chunkList = *i;
std::list<iof_chunk>::iterator j = *i.begin();
for(; j != *i.end(); ++j) {
/* do your operation with *j that is an iof_chunk object */
}
}
First of all this statement is invalid because there is no identifier that is being declared.
std::list< std::list<iof_chunk> >::iterator;
As for your question then you can use the following construction
for ( iof_chunk &chunk : ALL_CHUNKS.back() )
{
// do something
}
A rather easy way to do this is with the auto keyword, like so..
auto iter = myList.begin();
This is equivalent to..
std::list< std::list<T> >::iterator iter = myList.begin();
The thing to remember is that every level of list you add will add a corresponding iterator between you and the type T
So for example, if we have two lists ie. std::list<std::list<T>> we'll need to use two iterators to get to any T values.
std::list<std::list<T>> myList;
auto iter1 = myList.begin();
auto iter2 = iter1->begin();
T value = *iter2; //assuming iter2 != iter1->end()
So for a moderately more complex example, with a more useful bit of code supporting it, take the following..
//list x 4
std::list< std::list< std::list< std::list<T> > > > myCrazyList;
for(auto iter1 = myCrazyList.begin(); iter1 != myCrazyList.end(); ++iter1){
for(auto iter2 = iter1->begin(); iter2 != iter1->end(); ++iter2){
for(auto iter3 = iter2->begin(); iter3 != iter2->end(); ++iter3){
for(auto iter4 = iter3->begin(); iter4 != iter3->end(); ++iter4){
T& value = *iter4;
//do stuff to your T
}
}
}
}
As you can see auto can be instrumental in keeping sane when dealing with long types like this. iter4 would be equivalent to std::list<T>::iterator but iter1 on the other hand has all 4 std::list in the type-name.
How can I can gain access to a map which is stored in std::set? I need to do something like
for (iterator=map.begin(); iterator!=map.end(); iterator++) {
some_function(iterator->first);
}
, but instead of map im using set containing maps.
It's not very different from iterating any other map.
set<map<int, int> > s;
for (set<map<int, int> >::iterator it = s.begin(); it != s.end(); ++it) {
for (map<int, int>::iterator iter = it->begin(); iter != it->end(); ++iter) {
.. do something ...
}
}
So first you iterate over the set and then over the elements of the map pointed to by the outer container's iterator. I have used map<int, int> here just for illustration.
Using range-for makes this much simpler (assuming I understand your question):
for (map<int, int>& m : my_set) {
some_function(m);
}
I have this code:
std::set<unsigned long>::iterator it;
for (it = SERVER_IPS.begin(); it != SERVER_IPS.end(); ++it) {
u_long f = it; // error here
}
There is no ->first value.
How I can obtain the value?
You must dereference the iterator in order to retrieve the member of your set.
std::set<unsigned long>::iterator it;
for (it = SERVER_IPS.begin(); it != SERVER_IPS.end(); ++it) {
u_long f = *it; // Note the "*" here
}
If you have C++11 features, you can use a range-based for loop:
for(auto f : SERVER_IPS) {
// use f here
}
Another example for the C++11 standard:
set<int> data;
data.insert(4);
data.insert(5);
for (const int &number : data)
cout << number;
Just use the * before it:
set<unsigned long>::iterator it;
for (it = myset.begin(); it != myset.end(); ++it) {
cout << *it;
}
This dereferences it and allows you to access the element the iterator is currently on.
How do you iterate std::set?
int main(int argc,char *argv[])
{
std::set<int> mset;
mset.insert(1);
mset.insert(2);
mset.insert(3);
for ( auto it = mset.begin(); it != mset.end(); it++ )
std::cout << *it;
}
One more thing that might be useful for beginners is , since std::set is not allocated with contiguous memory chunks , if someone want to iterate till kth element normal way will not work.
example:
std::vector<int > vec{1,2,3,4,5};
int k=3;
for(auto itr=vec.begin();itr<vec.begin()+k;itr++) cout<<*itr<<" ";
std::unordered_set<int > s{1,2,3,4,5};
int k=3;
int index=0;
auto itr=s.begin();
while(true){
if(index==k) break;
cout<<*itr++<<" ";
index++;
}