Push_back into map<int,vector<char>>* - c++

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

Related

how to traverse in a unordered_map of unordered_map of unordered_map in c++

I wanted to traverse inside a data structure - unordered_map<int, unordered_map<int, unordered_map<int, int>>> myMap. To further specify I want to get the data elements like ->
myMap[someVal1][someVal2]
{all second elements of this unordered map}
I am aware of the fact that the same could by done by a 3d array however using a 3d array would not be efficient as the data range is huge and the program would end up using far more space than required.I tried using some iterators like unordered_map<int, unordered_map<int, unordered_map<int, int>>>::iterator i, and several other such iterators however it always ends up in some error or the other. Could someone help me in understanding how this map can be traversed ? Thanks in advance!
You could traverse the map with a foreach loop (it needs C++11, I think that won't be a problem), if you don't want to use iterators.
myMap mapMapMap;
for(auto& mapMap : mapMapMap){
for(auto& map : mapMap.second){
for(auto& key_value : map.second){
int key = key_value.first;
int value = key_value.second;
// ....
}
}
}
Also, if you didn't want to iterate all the map, but only the values of the third level, given the two first, then this should make it:
int k1, k2;
for(auto& key_value : myMap.at(k1).at(k2)){
//...
}

How to extract the value of the pair retuned by unordered_map::emplace?

I'm trying to make my code 1 line shorter, a noble cause. I have this unordered map
std::unordered_map<std::string, int> um;
and I want to assign the integer to a variable on the same line where I emplace a pair into the unordered map like so
int i_want_132_here = um.emplace("hi", 132).first.???;
problem is, I have no idea what to do with [return value of unordered_map::emplace].first
In the debugger I can see that "first" contains ("hi", 132) but how do I access those values?
emplace returns a pair<iterator, bool>.
So you should do:
int i_want_132_here = (*um.emplace("hi", 132).first).second;
alternative syntax:
int i_want_132_here = um.emplace("hi", 132).first->second;
In general I prefer (*it) form instead of it->.

Loss of data while ordering an unordered_map c++

I have a unordered_map<string, int> freq and I order it transforming it into a
map<int,string> freq2. I use the next function in order to do that:
map<int, string> order(unordered_map<string, int> x) {
map <int, string> map;
for (auto it = x.begin(); it != x.end(); ++it) {
map.emplace(it->second, it->first);
}
return map;
}
the size of the unordered_mapis 2355831 and the returned map is 505, so as you see the loss of data is quite big and i have no idea why....
Any idea why this happens?
Thanks.
EDIT:
Thanks to all, you are all right, I have a lot of int with same value, that´s why i loose the data( really stupid from my part to not see it before)
Most likely this is because there are duplicates among the int values. Try replacing map<int, string> with multimap<int, string>.
The code itself looks fine. However, since you are mapping from string keys to integers, it might be very well that you have multiple keys with the same value.
From the documentation of emplace:
The insertion only takes place if no other element in the container has a key equivalent to the one being emplaced (keys in a map container are unique).
So if a lot of your entries in the first map have the same value (which is the key in the second map), then your dataset will decrease by a lot.
If you need to preserve those elements, then std::map is not the right container.

3 element multimap, sort by the first but count the second number

I'm using std::multimap in this way
std::multimap<float, std::pair<int, int> > edges;
I want to sort it by the first float number, but later count how many int (the first one of <int, int>) are in this multimap.
for example,
I have element pairs (0.6001, <2,3>), (0.62, <2,4>), (0.63, <1,3>) in my multimap,
I want to count the number of <2,*> (it should be 2 here).
Is there a simpler way (something like edges.count()) than to get every element out and count?
Or is there another container that I could turn to?
#
Solution 1
I'll first store the values I need to count in a std::set and count as codes given by jrok or johny;
Solution 2
I'll use a std::multimap to store the second and third element again and count.
Thank you both jrok and johny!
What about this?
std::multimap<float, std::pair<int, int> > edges;
typedef std::multimap<float, std::pair<int, int> >::value_type ElemT;
int value = 2;
int count =
std::count_if(edges.begin(), edges.end(),
[value](const ElemT& e) { return e.second.first == value; });

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.