How to insert data into nested map in c++? - c++

//I am reading data from file and storing data into structure.Here "obj" is a object of structure.
Also note that my file have outer map key multiple times means when i am reading from file then some field of structure has common value and i am using that common value as a key of outer loop.
If I have only single value of outer key then it works fine but when more than one value of key then it fails.
typedef std::map<double,Order_Msg,std::greater<double> >InnerMap;
typedef std::map<int, InnerMap> OuterMap;
InnerMap buy_detailsmap;
OuterMap buy_tokenmap;
//one way
buy_tokenmap.insert(make_pair(obj.token,InnerMap()));
buy_detailsmap.insert(make_pair(obj.orderId,obj));
//another way
buy_detailsmap.insert (std::pair<double,Order_Msg>(obj.orderId,obj));
buy_tokenmap.insert(std::make_pair(obj.token,buy_detailsmap));
I tried both but its not working properly.

It isn't clear why you need buy_detailsmap, as it is de-coupled from buy_detailsmap. Unless you really need insert's semantics, you could simply use operator[]:
buy_tokenmap[obj.token][obj.orderId] = obj;

Related

Inserting into Map of String keys and Vector values

I'm a smidge rusty on using map and need a lil' help; I've declared the below.
std::map<std::string, std::vector<double>> myMap;
I'm periodically reading JSON data, where the ordering of data may sometimes change, or new data elements appear. Other parts of my code will loop through the JSON and extract two variables (jsonLabel, a string), and the associated value as a double (latestDouble).
If jsonLabel already exists, I want to add the associated latestDouble to the end of the vector; if it doesn't exist, make the new Key and start a vector.
I've tried the below; however I keep crashing. I'm presuming it's because map actually isn't smart enough to insert latestDouble at the end of the vector in the map.
myMap.insert(std::make_pair(jsonLabel, latestDouble));
Pseudo Example:
JSON parse #1: [A,43],[B,10],[C,9]
JSON parse #2: [A,10],[C,4],[B,3] /// Change in ordering
JSON parse #2: [A,8],[B,7],[C,2],[D,1] /// New element
Should result in:
A: 43,10,8
B: 10,3,7
C: 9,4,2
D: 1
Thanks for any help!
If the string in jsonLabel already exists as a key in the map, then insert will not insert anything into the map.
And the map insert function is to insert into the map itself. The pair should be a pair of the key and value types (where the value should be a vector of doubles).
What you seem to want is simply
myMap[jsonLabel].push_back(latestDouble);
The operator[] function will create a default-constructed value if the key doesn't exist, and as such will create an empty vector for you.

How to store the addresses of different unordered map into another unordered map and then use them for by referencing?

I save integer values in 2 different unordered_map, say, map1 and map2. Now, I save the address of these maps into another master unordered map,say, arr_maps using some key already defined. Now, I want to access the corresponding map based on the value of the key. The value is the memory address of map1/map2. I pass these addresses to a function to access them because I don't to copy the whole map into another map, just wanna reference it. I am not able to do that. Getting no reference the map but the code is building
I have tried referencing but it doesn't work
**#header files here**
unordered_map<string, unordered_map<ui,ui>*> arr_map; //Global declaration
function test(unordered_map<ui,ui>& cmap)
{
ui deg_index;
unordered_map<ui, ui>::const_iterator get = cmap.find(0);
//"0" is present in cmap, but not able to reference the map
if(get_node_deg == curr_node_deg.end())
//do something
}
main()
{
unordered_map<ui, ui> map1,map2;
map1.emplace(0,0);
map1.emplace(1,1);
arr_map.emplace("01",&map1);
map2.emplace(0,1);
map2.emplace(1,2);
arr_map.emplace("12",&map2);
test(arr_map["01"]);//not able to reference it
// want to pass the reference of map 1 and use it, instead of copying the whole map
test(arr_map["12"]);//same here
}

std::unordered_set::find - construct an instance only for find()

A lot of times I see my key is actually inside my value.
For example:
struct Elem {
int key;
// ... Other variables ...
}
That makes me want to use std::unordered_set instead of std::unordered_map, because I already have the key stored inside my value - no need to waste more place for std::unordered_map's .first (key).
Then I start implementing with std::unordered_set and get to the place I need to perform a find() over my std::unordered_set.
Then I realize I need to create an empty-shell Elem so I would be able to find(), beacuse std::unordered_set::find gets a Key for input
template < class Key, // unordered_set::key_type/value_type
class Hash = hash<Key>, // unordered_set::hasher
class Pred = equal_to<Key>, // unordered_set::key_equal
class Alloc = allocator<Key> // unordered_set::allocator_type
> class unordered_set;
Sometimes building an empty-shell Elem is hard / wasteful / maybe even not possible?
For example, when my key/value is
An iterator
A reference
A class with specific c'tor (not constructing the instance only with the key)
Q. Am I missing something?
Q. Is there a way to do find() that isn't wasteful? I mean that doesn't make me create an instance I didn't want to
Something really strange to me - that I already should have the element I'm looking for in order to find it, or at least an empty-shell of it.
When choosing a data structure to hold your data you need to consider your use case.
If you want to look up data from a key you should use a map. If you just want to store unique values in a collection and you don't need to look them up use set.
I don't see why its so much trouble to insert a element as map.emplace_back(elem.key, elem) vs set.emplace_back(elem) if it means that down the road you can just query the elem as map.at(key) or map[key] vs having create an empty elem.
Besides, std::set does the whole key thingamajig (roughly) underwater anyway. (source: What is the difference between set vs map in C++?)

Use of List inside map C++

Can I use following syntax:
std::map<int,std::list<int>> mAllData;
Where Key Value(int) will be ID of data, and said data could have multiple types so storing all them against said key value. I am trying to use it.
std::map<int,std::list<int>> my_map;
my_map[10].push_back(10000);
my_map[10].push_back(20000);
my_map[10].push_back(40000);
Your compiler may not support the two closing angle brackets being right next to each other yet, so you might need std::map<int,std::list<int> > my_map.
With C++11 my_map can be initialized more efficiently:
std::map<int,std::list<int>> my_map {{10, {10000,20000,40000}}};
Also, if you just want a way to store multiple values per key, you can use std::multimap.
std::multimap<int,int> my_map;
my_map.insert(std::make_pair(10,10000));
my_map.insert(std::make_pair(10,20000));
And in C++11 this can be written:
std::multimap<int,int> my_map {{10,10000},{10,20000}};

Address of map value

I have a settings which are stored in std::map. For example, there is WorldTime key with value which updates each main cycle iteration. I don't want to read it from map when I do need (it's also processed each frame), I think it's not fast at all. So, can I get pointer to the map's value and access it? The code is:
std::map<std::string, int> mSettings;
// Somewhere in cycle:
mSettings["WorldTime"] += 10; // ms
// Somewhere in another place, also called in cycle
DrawText(mSettings["WorldTime"]); // Is slow to call each frame
So the idea is something like:
int *time = &mSettings["WorldTime"];
// In cycle:
DrawText(&time);
How wrong is it? Should I do something like that?
Best use a reference:
int & time = mSettings["WorldTime"];
If the key doesn't already exist, the []-access will create the element (and value-initialize the mapped value, i.e. 0 for an int). Alternatively (if the key already exists):
int & time = *mSettings.find("WorldTime");
As an aside: if you have hundreds of thousands of string keys or use lookup by string key a lot, you might find that an std::unordered_map<std::string, int> gives better results (but always profile before deciding). The two maps have virtually identical interfaces for your purpose.
According to this answer on StackOverflow, it's perfectly OK to store a pointer to a map element as it will not be invalidated until you delete the element (see note 3).
If you're worried so much about performance then why are you using strings for keys? What if you had an enum? Like this:
enum Settings
{
WorldTime,
...
};
Then your map would be using ints for keys rather than strings. It has to do comparisons between the keys because I believe std::map is implemented as a balanced tree. Comparisons between ints are much faster than comparisons between strings.
Furthermore, if you're using an enum for keys, you can just use an array, because an enum IS essentially a map from some sort of symbol (ie. WorldTime) to an integer, starting at zero. So then do this:
enum Settings
{
WorldTime,
...
NumSettings
};
And then declare your mSettings as an array:
int mSettings[NumSettings];
Which has faster lookup time compared to a std::map. Reference like this then:
DrawText(mSettings[WorldTime]);
Since you're basically just accessing a value in an array rather than accessing a map this is going to be a lot faster and you don't have to worry about the pointer/reference hack you were trying to do in the first place.