I wanted to know if there was a way to find an int in a double type map container. For instance in the following example
std::map<double,double> mt;
mt[2.33] =3.45;
if(mt.find(2)!=mt.end()) //How to do a search for an int instead of a map
{
//Found
}
I wanted to know if there was a way to tell the map to search for an int instead of a double. Since the map would search for a double by default.
One way you can do this is to use lower_bound/upper_bound member functions to get a range of values around your integer, and then check this range manually.
Other way is to use a map with custom comparator that compares keys as integers (see std::map referernce), so you preserve initial key values and can search for integers. But you can't search for doubles then.
Anyways, the task is a bit strange, you probably should reconsider your data structures choice for your problem.
The following should work:
it = mt.lower_bound(2);
However, you need to check the item afterwards;
it->first<3;
must yield true for correct result.
if you are interested only in the integral part (or anything else, as you can use a lambda for that), you might use
auto result = find_if(begin(mt), end(mt),
[&](pair<double, double> p){return (int)(p.first) == 2)}
)
if (result != mt.end())
{
// do your stuff
}
The use case for such a kind of approach still remains unclear...
Related
I have nested map of type:
std::map<int,std::map<pointer,pointer>>
I am iterating over the map each time/per frame and doing updates on it.So basically I have 2 nested if loops.
i have an array and i need to sort the data with 2 attributes. First attribute is integer which is the first key, then second attribute is a pointer which is a key of nested map inside the main map. so my code is something like:
iterator = outermap.find();
if(iterator!=outermap.end()){
value = iterator->second;
it1 = value.find();
if(it1!=value.end(){
value1 = it1->second;
// do something
}
else{
// do something and add new value
}
}
else {
// do something and add the values
}
This is really slow and causing my application to drop frame rate. Is there any alternative to this? Can we use hash codes and linked list to achieve the same?
You can use std::unordered_map, it will hash the keys so finds complete faster. Using value = iterator->second is copying your entire map to the 'value' variable. Using a reference avoids unnecessary copying and is better for performance, eg: auto & value = iterator->second.
Also std::map is guaranteed to be ordered. This can be used to your advantage since your keys are integers for the outermost map.
Firstly, your question is a bit vague, so this may or may not fit your problem.
Now, you have a map<int, map<pointer, pointer>>, but you never operate on the inner map itself. All you do is look up a value by an int and a pointer. This is also exactly what you should do instead, use an aggregate of those two as key in a map. The type for that is pair<int, pointer>, the map then becomes a map<pair<int, pointer>, pointer>.
One more note: You seem to know the keys to search in the map in advance. If the check whether the element exists is not just for safety, you could also use the overloaded operator[] of the map. The lookup then becomes outermap[ikey][pkey] and returns a default-initialized pointer (so probably a null pointer, it pointer really is a pointer). For the suggested combined map, the lookup would be outermap[make_pair(ikey, pkey)].
OK, so the task is this, I would be given (x, y) co-ordinates of points with both (x, y) ranging from -10^6 to 10^6 inclusive. I have to check whether a particular point e.g. (x, y) tuple was given to me or not. In simple words how do i answer the query whether a particular point(2D) is set or not. So far the best i could think of is maintaining a std::map<std::pair<int,int>, bool> and whenever a point is given I mark it 1. Although this must be running in logarithmic time and is fairly optimized way to answer the query I am wondering if there's a better way to do this.
Also I would be glad if anyone could tell what actually complexity would be if I am using the above data structure as a hash.I mean is it that the complexity of std::map is going to be O(log N) in the size of elements present irrespective of the structure of key?
In order to use a hash map you need to be using std::unordered_map instead of std::map. The constraint of using this is that your value type needs to have a hash function defined for it as described in this answer. Either that or just use boost::hash for this:
std::unordered_map<std::pair<int, int>, boost::hash<std::pair<int, int> > map_of_pairs;
Another method which springs to mind is to store the 32 bit int values in a 64 bit integer like so:
uint64_t i64;
uint32_t a32, b32;
i64 = ((uint64_t)a32 << 32) | b32;
As described in this answer. The x and y components can be stored in the high and low bytes of the integer and then you can use a std::unordered_map<uint64_t, bool>. Although I'd be interested to know if this is any more efficient than the previous method or if it even produces different code.
Instead of mapping each point to a bool, why not store all the points given to you in a set? Then, you can simply search the set to see if it contains the point you are looking for. It is essentially the same as what you are doing without having to do an additional lookup of the associated bool. For example:
set<pair<int, int>> points;
Then, you can check whether the set contains a certain point or not like this :
pair<int, int> examplePoint = make_pair(0, 0);
set<pair<int, int>>::iterator it = points.find(examplePoint);
if (it == points.end()) {
// examplePoint not found
} else {
// examplePoint found
}
As mentioned, std::set is normally implemented as a balanced binary search tree, so each lookup would take O(logn) time.
If you wanted to use a hash table instead, you could do the same thing using std::unordered_set instead of std::set. Assuming you use a good hash function, this would speed your lookups up to O(1) time. However, in order to do this, you will have to define the hash function for pair<int, int>. Here is an example taken from this answer:
namespace std {
template <> struct hash<std::pair<int, int>> {
inline size_t operator()(const std::pair<int, int> &v) const {
std::hash<int> int_hasher;
return int_hasher(v.first) ^ int_hasher(v.second);
}
};
}
Edit: Nevermind, I see you already got it working!
This might seem like a weird question, but how would I create a C++ function that tells whether a given C++ function that takes as a parameter a variable of type X and returns a variable of type X, is injective in the space of machine representation of those variables, i.e. never returns the same variable for two different variables passed to it?
(For those of you who weren't Math majors, maybe check out this page if you're still confused about the definition of injective: http://en.wikipedia.org/wiki/Injective_function)
For instance, the function
double square(double x) { return x*x};
is not injective since square(2.0) = square(-2.0),
but the function
double cube(double x) { return x*x*x};
is, obviously.
The goal is to create a function
template <typename T>
bool is_injective(T(*foo)(T))
{
/* Create a set std::set<T> retVals;
For each element x of type T:
if x is in retVals, return false;
if x is not in retVals, add it to retVals;
Return true if we made it through the above loop.
*/
}
I think I can implement that procedure except that I'm not sure how to iterate through every element of type T. How do I accomplish that?
Also, what problems might arise in trying to create such a function?
You need to test every possible bit pattern of length sizeof(T).
There was a widely circulated blog post about this topic recently: There are Only Four Billion Floats - So Test Them All!
In that post, the author was able to test all 32-bit floats in 90 seconds. Turns out that would take a few centuries for 64-bit values.
So this is only possible with small input types.
Multiple inputs, structs, or anything with pointers are going to get impossible fast.
BTW, even with 32-bit values you will probably exhaust system memory trying to store all the output values in a std::set, because std::set uses a lot of extra memory for pointers. Instead, you should use a bitmap that's big enough to hold all 2^sizeof(T) output values. The specialized std::vector<bool> should work. That will take 2^sizeof(T) / 8 bytes of memory.
Maybe what you need is std::numeric_limits. To store the results, you may use an unordered_map (from std if you're using C++11, or from boost if you're not).
You can check the limits of the data types, maybe something like this might work (it's a dumb solution, but it may get you started):
template <typename T>
bool is_injective(T(*foo)(T))
{
std::unordered_map<T, T> hash_table;
T min = std::numeric_limits<T>::min();
T max = std::numeric_limits<T>::max();
for(T it = min; i < max; ++i)
{
auto result = hash_table.emplace(it, foo(it));
if(result.second == false)
{
return false;
}
}
return true;
}
Of course, you may want to restrict a few of the possible data types. Otherwise, if you check for floats, doubles or long integers, it'll get very intensive.
but the function
double cube(double x) { return x*x*x};
is, obviously.
It is obviously not. There are 2^53 more double values representable in [0..0.5) than in [0..0.125).
As far as I know, you cannot iterate all possible values of a type in C++.
But, even if you could, that approach would get you nowhere. If your type is a 64 bit integer, you might have to iterate through 2^64 values and keep track of the result for all of them, which is not possible.
Like other people said, there is no solution for a generic type X.
Requirements:
container which sorts itself based on numerically comparing the keys (e.g. std::map)
check existence of key based on float tolerance (e.g. map.find() and use custom comparator )
and the tricky one: the float tolerance used by the comparator may be changed by the user at runtime!
The first 2 can be accomplished using a map with a custom comparator:
struct floatCompare : public std::binary_function<float,float,bool>
{
bool operator()( const float &left, const float &right ) const
{
return (fabs(left - right) > 1e-3) && (left < right);
}
};
typedef std::map< float, float, floatCompare > floatMap;
Using this implementation, floatMap.find( 15.0001 ) will find 15.0 in the map.
However, let's say the user doesn't want a float tolerance of 1e-3.
What is the easiest way to make this comparator function use a variable tolerance at runtime? I don't mind re-creating and re-sorting the map based on the new comparator each time epsilon is updated.
Other posts on modification after initialization here and using floats as keys here didn't provide a complete solution.
You can't change the ordering of the map after it's created (and you should just use plain old operator< even for the floating point type here), and you can't even use a "tolerant" comparison operator as that may vioate the required strict-weak-ordering for map to maintain its state.
However you can do the tolerant search with lower_bound and upper_bound. The gist is that you would create a wrapper function much like equal_range that does a lower_bound for "value - tolerance" and then an upper_bound for "value + tolerance" and see if it creates a non-empty range of values that match the criteria.
You cannot change the definition of how elements are ordered in a map once it's been instantiated. If you were to find some technical hack to do so (such as implementing a custom comparator that takes a tolerance that can change at runtime), it would evoke Undefined Behavior.
Your main alternative to changing the ordering is to create another map with a different ordering scheme. This other map could be an indexing map, where the keys are ordered in a different way, and the values arent the elements themselves, but an index in to the main map.
Alternatively maybe what you're really trying to do isn't change the ordering, but maintain the ordering and change the search parameters.
That you can do, and there are a few ways to do it.
One is to simply use map::lower_bound -- once with the lower bound of your tolerance, and once with the upper bound of your tolerance, just past the end of tolerance. For example, if you want to find 15.0 with a tolerance of 1e-5. You could lower_bound with 14.99995 and then again with 15.00005 (my math might be off here) to find the elements in that range.
Another is to use std::find_if with a custom functor, lambda, or std::function. You could declare the functor in such a way as to take the tolerance and the value at construction, and perform the check in operator().
Since this is a homework question, I'll leave the fiddly details of actually implementing all this up to you. :)
Rather than using a comparator with tolerance, which is going to fail in subtle ways, just use a consistent key that is derived from the floating point value. Make your floating point values consistent using rounding.
inline double key(double d)
{
return floor(d * 1000.0 + 0.5);
}
You can't achieve that with a simple custom comparator, even if it was possible to change it after the definition, or when resorting using a new comparator. The fact is: a "tolerant comparator" is not really a comparator. For three values, it's possible that a < c (difference is large enough) but neither a < b nor b < c (both difference too small). Example: a = 5.0, b = 5.5, c = 6.0, tolerance = 0.6
What you should do instead is to use default sorting using operator< for floats, i.e. simply don't provide any custom comparator. Then, for the lookup don't use find but rather lower_bound and upper_bound with modified values according to the tolerance. These two function calls will give you two iterators which define the sequence which will be accepted using this tolerance. If this sequence is empty, the key was not found, obviously.
You then might want to get the key which is closest to the value to be searched for. If this is true, you should then find the min_element of this subsequence, using a comparator which will consider the difference between the key and the value to be searched.
template<typename Map, typename K>
auto tolerant_find(const Map & map, const K & lookup, const K & tolerance) -> decltype(map.begin()) {
// First, find sub-sequence of keys "near" the lookup value
auto first = map.lower_bound(lookup - tolerance);
auto last = map.upper_bound(lookup + tolerance);
// If they are equal, the sequence is empty, and thus no entry was found.
// Return the end iterator to be consistent with std::find.
if (first == last) {
return map.end();
}
// Then, find the one with the minimum distance to the actual lookup value
typedef typename Map::mapped_type T;
return std::min_element(first, last, [lookup](std::pair<K,T> a, std::pair<K,T> b) {
return std::abs(a.first - lookup) < std::abs(b.first - lookup);
});
}
Demo: http://ideone.com/qT3JIa
It may be better to leave the std::map class alone (well, partly at least), and just write your own class which implements the three methods you mentioned.
template<typename T>
class myMap{
private:
float tolerance;
std::map<float,T> storage;
public:
void setTolerance(float t){tolerance=t;};
std::map<float,T>::iterator find(float val); // ex. same as you provided, just change 1e-3 for tolerance
/* other methods go here */
};
That being said, I don't think you need to recreate the container and sort it depending on the tolerance.
check existence of key based on float tolerance
merely means you have to check if an element exists. The position of the elements inside the map shouldn't change. You could start the search from val-tolerance, and when you find an element (the function find returns an iterator), get the next elements untill you reach the end of the map or untill their values exceed val+tolerance.
That basically means that the behavior of the insert/add/[]/whatever functions isn't based on the tolerance, so there's no real problem of storing the values.
If you're afraid the elements will be too close to eachother, you may want to start the searching from val, and then gradually increase the toleration untill it reaches the user desired one.
I have defined a Map
boost::unordered_map<"std::string,std::string">m_mapABC ;
And I Store values in it Like m_mapABC[strValue1]=strValue2;
And Assume that i store 10 entries to the map.In that case can the same Key Value be used to store 10 different Values..or will it be over written every time...I guess it would.
In that case using std::pair would help i guess.
std::map<"std::string, std::pair<"std::string", bool>>myMap2
std::pair can have 2 Key Values Equal(I guess I am Right)...What will be the bool value in each case,will it be TRUE in the first case and FALSE the second time or vice-versa?.
I also heard about std::tuple or boost::tuple where a single Key can be used to Store Different Values.
I am not very clear about how to iterate through them...i need help
You may want multimap instead of map.
If you want to associate more than one value with a single key, use std::multimap (or std::unordered_multimap) instead of std::map.
In some cases, it can make sense to have a std::map<key_type, std::vector<mapped_type> > instead (personally, I frequently find this preferable).
If you want to store multiple items with the same key, you should use a multimap (also applies to unordered_ variants).
The following should work:
std::multimap<std::string,int> mm;
for( int i = 0; i != 10; ++i )
mm.insert(make_pair("hello world"), i);
And your multimap should contain ten entries with key "hello world" and 10 different values.