Nested Map, accesing inner map value - c++

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()){
(...)
}
}

Related

how to use find on a map of int,string

This is probably easy but i've been awake for too long.
So I have a map< int, string> and i'm trying to use the function find
iter=mapInKey.find(int)->second;
if (iter != mapInKey.end() )
{
outFileTxt << iter;
}
But I get this error: no matching function for call to std::map<int, std::basic_string<char> >::find(std::string&)
All I want to do is output the other pair value of int
Like this
std::map <int,std::string>::iterator it = mapInKey.find( val ); //val is the integer key you search for
if(it != mapInKey.end()){
// do something
cout<< it->second; // this will print the string
}
Edit
I think you want to search by string. then you are declaring the map wrong. Use this
map<string,int> m;
m["Hi"]= 1;
m["Hello"]= 2;
map<string,int>::iterator it = m.find("Hello");
if(it != m.end())
{
cout<< it->first<<":"<<it->second<<endl;
}

Add values to a std::multimap

I'm trying to print out the five most used values. But when I changed my map to a multimap I broke the code where I add values to the map. How can I add values to a multimap? Can it be done in a similar way as I add values to a map?
// Create a map for keeping track of how many occurences of the different colors
multimap<string, int> hexmap;
// Add the hex values to the map
for(int i = 0; i < imagesize; i ++)
{
hexmap[colors[i]]++;
}
typedef std::multimap<int, string> Mymap;
Mymap dst;
std::transform(hexmap.begin(), hexmap.end(),
std::inserter(dst, dst.begin()),
[](const std::pair<string,int> &p )
{
return std::pair<int, string>(p.second, p.first);
}
);
Mymap::iterator st = dst.begin(),it;
size_t count = 5;
for(it = st; ( it != dst.end() ) && ( --count ); ++it)
std::cout << it->second << it->first << endl;
You add elements to a std::multimap<K, V> using insert() or emplace(), e.g.:
std::multimap<std::string, int> map;
map.insert(std::make_pair("hello" , 1));
map.insert({ "world", 0 });
map.emplace("hello", 0);
You'd locate objects in the std::multimap<K, V> using it's find() member, e.g.:
std::multimap<std::string, int>::iterator it = map.find("hello");
"I'm trying to print out the five most used values."
In this case, you don't have to use hexmap as std::multimap just std::map will do the job
However std::multimap for dst should be required

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.

Browse vector with std::vector<std::pair < > >

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.

Copying C++ Map into key and value vectors

I have a map and I want the first column i.e (*it).first to be pushed back into a vector then (*it)->second to be pushed back into another vector
Is this the best way to do it?
std::vector<std::string>test;
for ( it=mymap.begin() ; it != mymap.end(); it++ )
{
test.push_back((*it).first);
}
My other question is if i have a loop i.e
how would I insert all the integers i into (*it).first?
for(int i = 0; i < 10; i++)
{
// 1 - 10 will go in (*it).first
}
I want to have some integers in (*it).first and have associated values in (*it).second;
Use std::transform.
First define two functions key and value which take the pair of strings and return the first or second value, respectively.
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
const std::string& key(const std::pair<std::string, std::string>& keyValue)
{
return keyValue.first;
}
const std::string& value(const std::pair<std::string, std::string>& keyValue)
{
return keyValue.second;
}
Then use std::transform from <algorithm> with the functions to transform the map into either a vector of keys or a vector of values.
int main()
{
using namespace std; // be explicit normally, trying to be brief here
map<string, string> contacts;
contacts["alice"] = "555-2701";
contacts["bob"] = "555-2702";
vector<string> keys(contacts.size());
vector<string> values(contacts.size());
transform(contacts.begin(), contacts.end(), keys.begin(), key);
transform(contacts.begin(), contacts.end(), values.begin(), value);
cout << "Keys:\n";
copy(keys.begin(), keys.end(), ostream_iterator<string>(cout, "\n"));
cout << "\n";
cout << "Values:\n";
copy(values.begin(), values.end(), ostream_iterator<string>(cout, "\n"));
return 0;
}
Output:
Keys:
alice
bob
Values:
555-2701
555-2702
Your first question, "how can I push the first column of my map into one vector and the 2nd column into another" is solved thus:
std::map<std::string, std::string> mymap;
std::vector<std::string> keys;
std::vector<std::string> values;
for ( std::map<std::string,std::string>::iterator it=mymap.begin() ; it != mymap.end(); ++it )
{
keys.push_back(it->first);
values.push_back(it->second);
}
Your second question, "how would insert all the integers i into (*it).first ?" is solved thus:
std::map<int, int> mymap2;
for(int i = 0; i < 10; i++)
{
// Insert default value into map
// This sets '(*it).first' to 'i' and
// '(*it).second' to a default value (in
// this case, 0).
mymap2[i];
}
or
std::map<int, int> mymap3;
for(int i = 0; i < 10; i++)
{
// Insert specified value into map
// this sets '(*it).first' to 'i', and
// '(*it).second' to the value returned from the function.
maymap3[i] = ChooseSpecificValue(i);
}
Well, it can be done with a simple loop:
for (auto const& p: mymap) {
vec1.push_back(p.first);
vec2.push_back(p.second);
}
Or using the std::transform algorithm, though it's quite verbose here:
std::transform(mymap.begin(), mymap.end(), std::back_inserter(vec1),
[](MyMap::const_reference p) { return p.first; });
Assuming you've declared your map as string key and value (ie map<string, string> mymap; then it would be like below, also assuming you've declare 'it' variable as map<string, string>::iterator it, etc:
std::vector<std::string> test;
std::vector<std::string> second;
std::map<string, string>::iterator it;
for ( it=mymap.begin() ; it != mymap.end(); it++ )
{
test.push_back((*it).first);
second.push_back((*it).second);
}
Not sure about your next question.
The first part of your question:
std::vector<std::string> test;
std::vector<std::string> test2; // assuming map is from string to string
for (it = mymap.begin(); it != mymap.end(); ++it)
{
test.push_back(it->first); // push first in one vector
test2.push_back(it->second); // push second in another vector
}
So, yes a simple for can do what you want.
The second part of your question:
Since you are updating the key of the map, you would need to remove it from the map and insert the changed one. So:
std::string first, second;
first = it->first;
second = it->second;
mymap.erase(it); // be careful with invalidating iterator
// change first
mymap[first] = second;
To change first by adding all integers i to it, that would really depend on the type of first. For example with a string, you may mean something like this:
ostringstream sout;
for (int i = 0; i < 10; ++i)
sout << (i?" ":"") << i;
first = sout.str();
Or if first is for example a set, you may mean something like this:
for (int i = 0; i < 10; ++i)
first.insert(i);
and my other question is if i have a loop i.e how would insert all the
integers i into (*it).first?
In the case of a std::map, you can't modify the iterator returned like that ... the key member (i.e., the first) in the std::map key/value pair data-structure is intentionally designated as a constant value, and is initialized to its constant value at the beginning of the key/value pair's lifetime in the std::map data-structure. If the keys weren't constant, you would end up creating havoc when you change the key, since the nodes in a std::map are suppose to be sorted by the keys. The second member of the key/value pair data-structure is the member that can be changed.
So if you want to insert a set of key/value pairs in a map, you could simply do the following:
std::map<int, int> mymap;
int some_other_value = 100;
for (int i=0; i < 10; i++)
{
mymap[i] = some_other_value++;
}
it here will be an iterator which will point to one of the position in map and at max have one first and second value for one iterator . At max you can have multiple key or same key holding same/different values depending on key/value combination.
As far as pushing the value in the vector for a key in map is concern you can do it in the same way you are pushing the key
std::vector<std::string>test;
std::vector<std::string>test2;
for ( it=mymap.begin() ; it != mymap.end(); it++ )
{
test.push_back((*it).first);
test2.push_back((*it).second);
}
Neways yours question is very unclear .
Just in case you want to deal with different data types in your map I would template a generic copy function:
template <class A, class B>
void mycopy(std::map<A, B>&m, std::list<A>& keys, std::list<B>& values) {
typename std::map<A, B>::iterator it;
for (it = m.begin(); it != m.end(); ++it) {
keys.push_back( (*it).first );
values.push_back( (*it).second );
}
}
Mixing it up:
std::map<int, std::string> mymap;
std::list<int> keys;
std::list<std::string> values;
mymap[1] = "string1";
mymap[2] = "string2";
mycopy(mymap, keys, values);
std::map<std::string, int> mymap1;
std::list<std::string> keys1;
std::list<int> values1;
mymap1["string1"] = 1;
mymap1["string2"] = 2;
mycopy(mymap1, keys1, values1);
Edit: yes __copy isnt the best definition. Thanks