two keys map in C++ - c++

I plan to use a map with two keys for my assignment. And I create my map like following:
map<pair<string, string>, int> myMap;
map<pair<string, string>, int>:: iterator it;
I had a hard time on how to use map.find() and map.insert() for finding existing entry in the map or insert a new value if two keys combination is new. Can some one give an example?

It should be the same as with any map, except you have to make pairs for your key.
Insert :
map< pair<string,string>, int > mymap;
pair<string, string> key = make_pair("bob", "sue");
mymap[ key ] = 5; // you can inline make_pair if you prefer.
// or you can use insert method
mymap.insert( key, 5 );
Find :
pair<string, string> key = make_pair("bob", "sue");
auto it = mymap.find( key ); // you can inline make_pair if you prefer.
if ( it != mymap.end() )
{
cout << it->second;
}
Note that using strings as a key in a map can have performance issues. Also, the order of the strings in the pair has significance.

it = myMap.find(make_pair("hi","mike"));
insert is a little awkward because you're inserting a pair whose first component is also a pair:
myMap.insert(make_pair( make_pair("hi","john"), 4 ) );

You should have a look at Boost multiIndex

This works:
typedef pair<string, string> key_type;
map<key_type, int> myMap;
myMap.insert(std::make_pair(key_type("a","b"),1));
map<pair<string, string>, int>::iterator it;
it = myMap.find(key_type("a","b"));
insert can be replaced with emplace in C++11 to shorten the code:
myMap.emplace(key_type("a","b"),1);

Related

Push_back into map<int,vector<char>>*

c++
map<int, vector>* maxcounts;
When I have a pointer to map maxcount how do I write this next statement correctly?
maxcounts[-m.second]->push_back(m.first);
without referencing a pointer I write
maxcounts[-m.second].push_back(m.first);
map<int, vector<char>> maxcounts;
for (pair<char, int> m : counts) {
if (maxcounts.count(-m.second))
maxcounts[-m.second].push_back(m.first);
else
maxcounts.insert({ -m.second, {m.first} });
}
To figure out how to use a pointer to the map, first rewrite your loop this way:
std::map<char, int> counts;
//...
std::map<int, std::vector<char>> maxcounts;
for (std::pair<char, int> m : counts)
maxcounts.insert({-m.second, std::vector<char>()}).first->second.push_back(m.first);
Note that the return value for std::map::insert is a std::pair, where the first of the pair is an iterator to the existing item if the item already is in the map, or the iterator to the newly inserted item. Thus you can perform the test and insert in one line without need for an if statement.
The push_back will occur, regardless of whether the item inserted in the map is new or if the item existed. Note that for a new entry, the std::vector being inserted starts as empty.
Given this, the pointer to the map version is very simple:
std::map<char, int> counts;
//...
map<int, vector<char>>* maxcounts;
//
for (pair<char, int> m : counts)
maxcounts->insert({-m.second, std::vector<char>()}).first->second.push_back(m.first);
Now, why you need a pointer to a map in the first place is another issue, but to answer your question, the above should work.
I would likely write something like:
std::map<int, std::vector<int>>* maxcounts = ...;
for (std::pair<char, int> m : counts)
(*maxcounts)[-m.second].push_back(m.first);

How to insert value in map?

I am having an issue with map.
map<int, map<int , int>> my_map;
I am using insert() like:
my_map.insert(10, my_map.second.insert(20, 30));
but it's not working.
The method to insert into map in dictionary is add(key,value)
Your code my_map.insert(10, my_map.second.insert(20, 30)); will throw an error as `second' is not a method that can be called on map.
Here is what you can do to solve this issue:
map<int, map<int , int>> my_map;
map<int, int> my__second_map = new map<int,int>();
my_second_map.add(20,30);
my_map.add(10,my__second_map);
You need an iterator of map type to call second.
You could also use below code using map insert. You may also use pair data type.
#include <map>
#include <iostream>
int main()
{
std::map<int, std::map<int , int> > my_map;
std::map<int,int> data;
data.insert(std::pair<int,int>(20,30));
my_map.insert(std::pair<int,std::map<int,int> >(10, data));
return 0;
}

Inserting into nested map in C++

Assume I have a nested map of type pointer. Then is there a single line statement to insert into the nested map,
map<int, map<int, int> >* nestedMap;
Currently I am doing this in 2 steps. First creating innermap and then insert into outer map as below,
nestedMap->insert(make_pair(int, map<int, int>)(int, innermap));
If the map is not pointer type, then i can insert easily like this,
nestedMap[int][int] = int;
Is there any simple ways for inserting into nested map of type pointer ?
thanks
Prabu
map::operator[] automatically creates the key/value pair if it doesn't exist.
(That's why it's not const!)
So you don't need to create the inner map manually.
If you want to avoid creating the pair automatically, then use map::find() or map::at().
I believe the simplest one-liner is:
(*nestedMap)[int][int] = int;
If i understand your question properly, you can actually use reference instead of pointer. You are not having issue with nested map, instead your outter map.
See below code, is what you want?
map<int, map<int, int> >* nestedMap = new map<int, map<int, int> >;
map<int, map<int, int> > &nestedMapAlais = *nestedMap;
nestedMapAlais[1][2] = 3;
access the operator[] via ->:
nestedMap->operator[](5)[6] = 7;
This is analogous to
nestedMap[5][6] = 7;
if nestedMap is not a pointer.
Note that in neither case do you have to explicitly insert a map.

Efficiently iterate multiple maps with the same keys

If I have two maps which are guaranteed to have exactly the same set of keys, how can I efficiently iterate through both maps?
For example, say I have the following maps:
std::map<std::string, int> iMap;
std::map<std::string, std::vector<int> > vMap;
At some point they both end up with exactly the same set of keys. I now need to update all values of vMap based on the corresponding iMap value. The first thing that comes to mind is something this:
typedef map<string, int> map_t;
BOOST_FOREACH(map_t::value_type &p, iMap) {
vMap[p.first].push_back(p.second);
}
However, it seems rather wasteful that we have to lookup each value of vMap[n] considering we're effectively going through the keys in order. Is there any way we can take advantage of this?
If you're absolutely sure that the keys are identical, you can iterate over both maps in lockstep:
auto it1 = iMap.begin();
auto it2 = vMap.begin();
while (it1 != iMap.end())
{
it2->second.push_back(*it1);
++it1;
++it2;
}

How can I access a specific element in a std::map with more than 2 elements?

I am trying to access a specific element out of a std::map with more than two elements. Here is an example:
std::map <int, CString, CString, CString> map;
//Initialise
map[0] = _T("stuff1"), _T("stuff2"), _T("stuff3");
//now if I just want to access stuff3 is it this:
CString str = map[0][2];
//or something more like this?
CString str = map[0]. ???
Any help would be great thanks.
edit: Thanks sorry about that, first time using maps, I was wondering why I couldn't find any information on std::map 's with more elements inside.
Have you tried to compile this? It shouldn't.
You can create only a map with exactly 1 key and 1 value for each element.
But the value can be compound, so you can write
struct ValueType {
CString v1;
CString v2;
CString v3;
}
std::map <int, ValueType> map;
and access elements like map[somekey].v3;
To insert a value in such a map, you'll have to write
ValueType strings = {"1","2","3"};
map.insert(999, strings);
Or you may create a helper function (i.e. void addToMap(std::map <int, ValueType> &map, CSting const& v1, CString const& v2, CString const& v3) ), which will fill your map in a more convenient way.
std::map <int, CString, CString, CString> map; is illegal.
Either use a std::multimap or a std::map<int,std::vector<CString> >.
I believe this what you are looking for
std::map <int, std::list<CString> > myMap;
then you'll access myMap[0], then access each element in the returned std::list<CString>