Browse vector with std::vector<std::pair < > > - c++

I have the following vector:
std::vector< std::pair<std::string,bool > > myvec;
How can i browse and print elements of my vector with iterators?

What is your problem?
typedef std::vector<std::pair<std::string, bool> > vector_type;
for (vector_type::const_iterator pos = myvec.begin();
pos != myvec.end(); ++pos)
{
std::cout << pos->first << " " << pos->second << std::endl;
}
or you can use std::for_each with some functor.

Create iterator, pointing to the first element of the vector (syntax: Container::iterator iter = myContainer.begin())
in a for-loop, iterate through all elements ( iterator has operator++; the end condition is - check if the iterator has reached the end of your container, like: iter != myContainer.end())
Iterators are like pointers, to reach it's members, use operator->.
std::pair is like a struct with two fields - first and second, so you can print a vector's element like: iter->first and iter->second.

Related

How to count how the number of elements stored in a vector which is stored in a map

I have four static vectors. In my .cpp file (not my .h file!) I define these vector as such:
std::vector<Object*> ClassA::vecA;
std::vector<Object*> ClassA::vecB;
std::vector<Object*> ClassA::vecC;
std::vector<Object*> ClassA::vecD;
Then I populate each of these vectors with a number of objects of type Object.
Next I create a map:
std::map<std::string, std::vector<Object*> > cntr;
I populate this map with the vectors from above and a string as a Key for each vector.
The question is, how do I access the vectors in the map to find out the number of elements they contain. I have tried:
for (it = Cntr.begin(); it != Cntr.end(); it++)
{
if (it->first != token)
{
std::cout << it->first << std::endl;
int i = (it->second).size();
std::cout << "SIZE: " << i << std::endl;
}
}
However i always gives me the value of 1. What is the correct approach?
First off you need to set the iterator to point to an valid element of the map. When you do
std::map<std::string, std::vector<Object*>>::iterator Class::it;
int size = it->second.size();
it doesn't point to anything so using it is undefined behavior. What you can do though is use
std::map<std::string, std::vector<Object*>>::iterator Class::it;
it = cntr.begin();
int size = it->second.size();
Which now gives you the size of the first vector in the map.
If you want to get all of the sizes then you will need to iterate through the map. You can do this with a nice ranged based for loop like
for (const auto & elem : cntr) // get a const reference to each pair
std::cout << elem.second.size();
NathanOliver's answer should work if you have C++11. If you don't, you can try this, with a typedef to make the code clear:
typedef std::vector<Object*> MypObjVec;
typedef std::map<std::string, MypObjVec> MyMap;
MyMap::iterator Class::it = cntr.begin();
const MyMap::iterator Class::it_end = cntr.end();
for(; it!=it_end ; ++it)
{
std::cout<< it->second.size() << std::endl;
}

Nested Map, accesing inner map value

For example I have a map like this:
map<string , map <int , int>> example;
and an iterator:
map<string , map <int, int>>::iterator iter;
string word;
And i want to access to the inner map :
for(iter = example.begin();iter!=example.end;iter++){
iter = Map.find(word);
iter -> second //
}
What i should do to access the inner map just for example if iter->second ==4 -it's is not correct ,
or can i do (iter->second)->second ??? can u give me an advise. i undestand that iterator is giving me a pair of (int,int) so i tryed to do another iterator map ::iterator i; and to assing iter->second = i, but it didin't help me to;
For complex types use typedef it will make your life much easier:
typedef std::map< int, int > Ints;
typedef std::map< std::string, Ints > String2Ints;
String2Ints example;
std::string word;
String2Ints::iterator it = example.find( word );
if( it != example.end() ) {
Ints &innerMap = it->second;
Ints::iterator innerit = innerMap.find( 4 );
if( innerit != innerMap.end() )
std::cout << "found value for word " << word << " 4 - " << innerit->second << std::endl;
}
Also your loop and find inside is incorrect, you should either iterate over map or search for value by find(), what you do in your code does not make any sense (technically infinite loop if word is found)
iter->second is a map, so if you want to find something in it you need another find.
You can also use your iterator directly, without the for loop.
Ex:
map<string , map <int, int>>::iterator iter;
iter = example.find(word);
if (iter != example.end()){
map<int, int>>::iterator innerIter;
int key = 4;
innerIter = iter->second.find(key);
if (innerIter != iter->second.end()){
(...)
}
}

a small issue with std::vector and changing the collection while looping through it

This loop changes the iterators while running:
std::vector<int> c;
c.push_back(1);
c.push_back(2);
std::vector<int>::iterator iter = c.begin();
std::vector<int>::iterator endIter = c.end();
while( iter != endIter )
{
std::cout << (*iter) << std::endl;
iter = c.erase(iter);
}
It does not work because:
Iterators and references to the erased elements and to the elements between them and the end of the container are invalidated. Past-the-end iterator is also invalidated
How can I rewrite this (without using std::list, and using the while loop) ?
By the way, I know that auto has been implemented since C++11. Why would it be beneficial to use it ?
Simply do not cache the end iterator that will be invalidated:
while( iter != c.end() )
{
std::cout << (*iter) << std::endl;
iter = c.erase(iter);
}
or clear the vector after printing:
for(const auto& i : c) {
std::cout << i << std::endl;
}
c.clear();
Erasing an element changes end(). Change the loop:
while( iter != c.end())
Either
Rewrite it as
while( iter != c.end() )
{
std::cout << (*iter) << std::endl;
iter = c.erase(iter);
}
and the code will no longer rely on any potentially invalidated iterators,
or
"Refresh" any potentially invalidated iterators after each invalidating operation
while( iter != endIter )
{
std::cout << (*iter) << std::endl;
iter = c.erase(iter);
endIter = c.end();
}
These are the two generic approaches typically used in cases like that.
A more idiomatic way of doing this...
while(c.begin() != c.end()) c.erase(c.begin());
Though this is very slow, as a vectors underlying implementation uses a contiguous array(with extra space on the end). So repeatedly erasing the begin element is very ineficient, as every element ends up getting copied one space in the array earlier, n - index times! You can jurastically increase performance by doing this:
while(c.begin() != c.end()) c.pop_back();

Iterator in std::set containing std::map

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

c++ hash_multimap how to get the values

This is probably really simple, but I can't find a simple example for it.
I understand that with a hash_multimap you can have several values mapped to a single key. But how exactly would I access those values. All the examples I stumbled across always just access the first value mapped to the the key. Heres an example of what I mean
key : value
1 : obj1a;
2 : obj2a, obj2b, obj2c
how would I access obj2b and obj2c, not just obj2a
The usual multimap iteration loop is like this:
#include <unordered_multimap>
typedef std::unordered_multimap<K, V> mmap_t;
mmap_t m;
for (mmap_t::const_iterator it1 = m.begin(), it2 = it1, end = m.end(); it1 != end; it1 = it2)
{
// outer loop over unique keys
for ( ; it1->first == it2->first; ++it2)
{
// inner loop, all keys equal to it1->first
}
}
To iterate over just one key value, use equal_range instead.
std::pair<mmap_t::const_iterator, mmap_t::const_iterator> p = m.equal_range(key);
for (mmap_t::const_iterator it = p.first; it != p.second; ++it)
{
// use "it->second"
}
For example, equal_range returns an two iterators, to the begin and end of the matching range :
void lookup(const map_type& Map, int key)
{
cout << key << ": ";
pair<map_type::const_iterator, map_type::const_iterator> p =
Map.equal_range(key);
for (map_type::const_iterator i = p.first; i != p.second; ++i)
cout << (*i).second << " ";
cout << endl;
}
where we're using a map_type like
class ObjectT; // This is the type of object you want to store
typedef hash_multimap<int, ObjectT> map_type;
Just grab an iterator to the first one and increment it. If the keys are still equal, you've got another entry with the same key value. You can also use equal_range.