c++ STL Map one key two values - c++

I have a situation where I have a map with one key and two values ex.
std::map<std::string, std::pair<double, double> > myMultiValueMap
depending on a condition I need to either update one value or the other.
I'd am looking for syntax to insert/ find the key and update either values in this map
yes I have used the insert on Maps before, but was not sure on multivalue map
std::map<std::string,double> myMap;
myMap.insert(std::make_pair("12345",0.00));
and find and update too
std::map<std::string,double>::iterator it = myMap.find(("12345");

std::map requires two template arguments, one key and one value type. But it is up to you to use arbitrary type for "value".
struct TestValue {
int Value1;
int Value2;
int Value3;
TestValue(int v1, int v2, int v3) : Value1(v1), Value2(v2), Value3(v3) {}
};
std::map<std::string, TestValue> myMap;
myMap["test"] = TestValue(1, 2, 3);

Inserting an item into the map:
myMultiValueMap[strKey] = make_pair(firstDouble, secondDouble);
Checking if an item exists:
if( myMultiValueMap.find(strKey) != myMultiValueMap.end() ) {
// Item Exists
}
Updating an item:
myMultiValueMap[strKey].first = newFirstDouble;
myMultiValueMap[strKey].second = newSecondDouble;
You should use this for these to work
using namespace std;
Please take time and read the examples from cplusplus.com

I like bkausbk's answer and would have commented on the answer but don't have rep. Map sometimes has a problem with needing a default constructor. I know this from another SO post. I got it to work by setting default arguments (the post has other solutions)
So I changed the constructor in bkausbk's answer to:
TestValue(int v1 = 0, int v2 = 0, int v3 = 0) : Value1(v1), Value2(v2), Value3(v3) {}

Related

C++ using an unordered key combination for a map lookup

I want to create an unordered_map, where the key is a combination of two integers. As the key values order shall be ignored when comparing, I thought of using an unordered_set as key like this:
#include <unordered_set>
#include <unordered_map>
using namespace std;
int main ()
{
unordered_set<int> key_set1 = {21, 42};
unordered_map<unordered_set<int>, char> map;
map[key_set1] = 'a';
...
unordered_set<int> key_set2 = {42, 21};
if(map[key_set2] == map[key_set2])
success();
}
On compile time it looks like some problem with the hash function:
error: no match for call to ‘(const std::hash<std::unordered_set<int> >) (const std::unordered_set<int>&)’
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
How can I solve this? Or is there a better way/data structure?
There is no predefined hash function for an unordered_set so you have to implement your own; there's documentation for that here http://en.cppreference.com/w/cpp/utility/hash.
Basically you'd need:
// custom specialization of std::hash can be injected in namespace std
namespace std
{
template<> struct hash<unordered_set<int>>
{
std::size_t operator()(unordered_set<int> const& s) const
{
std::size_t hash = 0;
for (auto && i : s) hash ^= std::hash<int>()(i);
return hash;
}
};
}
Now xor isn't the recommended way to combine hash functions, but it should work in this case specifically because it's both unordered and set. Because it's unordered you need a function that's commutative. The recommended hash combiners don't have this property as you usually want "abc" to hash differently than "bca". Secondly the fact that it's a set insures that you won't have any duplicate elements. This saves your hash function from failing because x ^ x == 0.
I should also mention that you want to define this in the cpp file so you don't expose this specific hash implementation on std types to everyone.
The problem is that unordered_set is not built for being used as a key in an unordered container.
If you always use exactly two ints, it would be more economical for you to use a pair of ints as a key, and add a function that makes a properly ordered pair from two integers:
pair<int,int> unordered_key(int a, int b) {
return a<b?make_pair(a, b):make_pair(b, a);
}
As pointed out earlier to use std::pair directly as a key you would need to explicitly define a hash function for it. If you want to avoid that, you can just do a bit-wise combination of 2 unsigned integers into 1:
uint64_t makeKey(uint32_t a, uint32_t b)
{
return a < b ? (static_cast<uint64_t>(a) << 32) + b : (static_cast<uint64_t>(b) << 32) + a;
}
int main ()
{
auto key_set1 = makeKey(21, 42);
unordered_map<uint64_t, char> map;
map[key_set1] = 'a';
//...
auto key_set2 = makeKey(42, 21);
if(map[key_set1] == map[key_set2])
std::cout << "success" << std::endl;
}
Since the order is not important here, you can use std::pair with a customized factory to force the order of the two integers:
std::pair<int, int> make_my_pair(int x, int y) {
return std::make_pair(std::min(x, y), std::max(x, y));
}
Of course this is only going to work if you use make_my_pair consistently.
Alternatively you can define your own key class that has a similar property.

How to read from a map in C++?

I have a map of std::map<int,float,float> m_mapWheelvalue; of 100 elements
I need to read the values .Code i am using is below:
float fvalue1,fvalue2;
std::map<double,float,float>::iterator itNewMap;
itNewMap= m_mapWheelvalue.find(20);
if(itNewMap!= m_mapWheelvalue.end())
{
fValue1 = itNewMap->second;
fValue2= itNewMap->third;
}
but its giving error !!{ third not defined }
How to read third value
Please give proper solution
The following compiled for me:
#include <map>
int main(){
std::map<double,std::pair<float,float> > m_mapWheelvalue;
float fValue1,fValue2;
std::map<double,std::pair<float,float> >::iterator itNewMap;
itNewMap= m_mapWheelvalue.find(20);
if(itNewMap!= m_mapWheelvalue.end()){
fValue1 = itNewMap->second.first;
fValue2= itNewMap->second.second;
}
}
Notes:
Look at std::map definition: first parameter is the key, second parameter is the entry... third parameter is the comparison function. I guess you wanted to have several values in the entry. I've chosen to use a pair (as you have two), if you have more you might want to define a struct/class.
Check variable names, there are several case changes.
The iterator to a map gets you a pair of key,entry... so itNewMap->first is the key, itNewMap->second is the entry.

Find in Vector of a Struct

I made the following program where there is a struct
struct data
{
int integers; //input of integers
int times; //number of times of appearance
}
and there is a vector of this struct
std::vector<data> inputs;
and then I'll get from a file an integer of current_int
std::fstream openFile("input.txt")
int current_int; //current_int is what I want to check if it's in my vector of struct (particularly in inputs.integers)
openFile >> current_int;
and I wanna check if current_int is already stored in my vector inputs.
I've tried researching about finding data in a vector and supposedly you use an iterator like this:
it = std::find(inputs.begin(),inputs.end(),current_int)
but will this work if it's in a struct? Please help.
There are two variants of find:
find() searches for a plain value. In you case you have a vector of data, so the values passed to find() should be data.
find_if() takes a predicate, and returns the first position where the predicates returns true.
Using the latter, you can easily match one field of your struct:
auto it = std::find_if(inputs.begin(), inputs.end(),
[current_int] (const data& d) {
return d.integers == current_int;
});
Note that the above uses a C++11 lambda function. Doing this in earlier versions of C++ requires you to create a functor instead.

Find and update an element in C++11 vector of structs

I have a vector of struct as follows
struct myStruct{
size_t aID;
int bID;
double tobeUpdated;
};
std::vector<myStruct> myVec;
how can I find and update a member of myVec which satisfies aID == someId && bID == otherID in an efficient way in C++11?
Assumes only one to be updated.
// what to search for
size_t aID = 5;
int bID = 7;
find_if(vec.begin(), vec.end(), [aID, bID](const myStruct& obj) { return obj.aID == aID && obj.bID == bID; });
If you want to make it more efficient, it really depends on your usage of the struct and array. If it is possible based on how you use it, then I would store them in an std::map instead. This will allow for easy lookup based on ID's or possibly a combination of ID's. However, if it doesn't actually slow your system down noticeably, then I would say to forgo the optimization and just iterate through each index with that test.

Access elements of map which is member of vector without creating copy

I have following data type
typedef std::map <std::string.std::string> leaf;
typedef std::map <std::string,leaf> child;
typedef std::vector<child> parent;
Now if I want access parent element at index 0 and child element having key "x" and then perform some operation of it's values
First way of doing this will be like:
parentobject[0]["x"]["r"]
But every time I need to repeat these index whenever I want access that value.
Second way of doing this will be like:
std::string value=parentobject[0]["x"]["r"]
Then use value object. But problem with this approach is this line will create copy of the string.
Is there a better way to access variable without creating copy?
You can use reference to avoid copy:
std::string & value = parentobject[x][y][z];
Or, will you be okay with this instead:
//define a lambda in the scope
auto get = [] (int x, std::string const & y, std::string const & z)
-> std::string &
{
return parentobject[x][y][z];
}
//then use it as many times as you want in the scope
std::string & value = get(0, "x", "r");
get(1, "y", "s") = "modify";
Use a reference:
const std::string& value = parentobject[0]["x"]["r"];
Now you can refer to value anywhere you like (within the same block scope) without having to perform the map lookups again.
Remove the const if you really need to.
Please purchase and read one of these books in order to learn C++'s basic features.