map inside map ( Map as key) - c++

I have created map inside following way.
Ex: map first;
and I have to created second map into following way as per my requirement.
map second.
So first is the key value for in second map.
I have inserted data into both map.
first.insert("Test1",1);
second.insert(first,2).
First Just I wantt to know is it correct way to do implementation. or Should I use another stl.?
I am facing one issue with this code (Not compliation issue). If I get data from database in following way than the value does not insert into second map.
first.insert("Test1",2);
second.insert(first,1). But I belive that it should enter into map as ("Test1" && 1) and
("Test" && 2) both are diffirent key for second map.

Why would you like to use a map as a key type?
Keys should be small, since you have no guarantee how many copies of them will STL do. Using (potentially large) std::map as a key will kill your apllication's performance.

First of all, for "STL", let me quote !stl from ##c++ at freenode:
`STL' is sometimes used to mean: (1) C++ standard library; (2) the library Stepanov designed at HP; (3) the parts of [1] based on [2]; (4) specific vendor implementations of either [1], [2], or [3]; (5) the underlying principles of [2]. As such, the term is highly ambiguous, and must be used with extreme caution. If you meant [1] and insist on abbreviating, "stdlib" is a far better choice.
Next: of course you can use map as key, but there is probably no comparator for it (I doubt there is std::less for map...). But remember - comparator doesn't check if parameters are equal - it checks, whether first is less than/greater than the second, because it's easier to model every possible relations using "less than":
a == b <=> !(a < b) && !(b < a)
And now, more ontopic:
From what you have written, I don't quite get the point of having map<map, anything else>. Could you provide some testcase? I will be able to give you complete answer, then.

Related

Can I check for a word inside of an array/vector without looping through it?

I believe that I can say...
for (int i = 0; i < noun[].size(); i++)
{
if ( word[0] == noun[i])
{ //do something }
}
The problem is, that I need to do this many times with many words. And sometimes I'd like to do many words at once. Like if (words[0] == noun[/*any*/] && words[1] == verb [/*any*/]) Is there any way to just tell it to check every element inside the array/vector against it?
Or maybe there is some container similar to an array that allows quick lookup?
I was only able to find a way to do it in python, but I never programmed in python so I'd like a way to do it in C++.
In python I found something like this:
a = [1,2,3,4,5]
b = 4
if b in a:
print("True!")
else:
print("False")
from here: Check if a value exists in an array in Cython
Unless there is some rule about the position of a particular element in a vector implying the position of another element, if present, the algorithm for the detection of presence must be O(N).
If the vector is sorted, for example, then a good positioning rule holds, and there are plenty of O(log(N)) algorithms out there: std::lower_bound is one such function.
The vector container isn't optimized for lookups. What you need is probably need a set. I recommend you check the answer to this question.
Considering your examples include verb and noun, you'll be trying to look up words in a (practically) fixed dictionary of sorts. There are many optimized containers for this purpose.
The Standard Library contains std::set<>, and a std::set<std::string> nouns will work. It has O(log N) lookup. Slightly more efficient, there's also std::unordered_map<>, which is still sufficient for your needs - you only need to know if a word occurs in the list of nouns, not what the next noun would be.
Outside the Standard Library, there are more data structures. A trie aka prefix tree shares the prefixes of its entries, which is space-efficient.

What does one put in emplace hint on unordered_multimap or unordered_map? [duplicate]

I know how to use std::unordered_map::emplace, but how do I use emplace_hint? Neither cplusplus nor cppreference provide a set of examples that illustrate how we might know where to put the element.
Can anyone provide some information on this or give some examples / illustrations of when we might know where the emplaced element should go?
What could an unordered_map potentially do with the hint? Well, if the iterator addresses an element with the same key as the element that emplace_hint has been asked to insert, then it can fail quickly - just a key comparison without any hashing or groping through any list of hash-colliding elements at that bucket. But if the key doesn't match, then the hint is otherwise useless because any other key - no matter how "close" in value - should (probabilistically) be at a completely unrelated bucket (given what's normally considered a "good" hash function), so time would have been wasted on a key comparison only to have to start over as if it were a normal emplace.
This might be useful when you're inserting pre-sorted-by-key elements, aiming to remove lots of duplicates in the process, but the key is so huge it's easier to keep an iterator to the just-inserted element than a copy of the key, or perhaps the hash function is particularly slow.
Another benefit of unordered_map::emplace_hint is better API compatibility with map::emplace_hint, so code can switch the container type and have the emplace_hints not break the compile, though they might end up slower than if the code were switched to emplace() as the close-but-different-key hints that help with a map may be useless with an unordered_map.
Just taking GCC 10.2 g++ -E output to see if it does what's described above. emplace_hint calls down into _M_insert_multi_node(...) wherein there's this line:
__node_base* __prev = __builtin_expect(__hint != nullptr, false)
&& this->_M_equals(__k, __code, __hint)
? __hint
: _M_find_before_node(__bkt, __k, __code);
Above, __k is the key that may be inserted, __code is the hash code, __hint is the hint iterator/pointer; _M_equals(...) returns:
return _Equal_hash_code<__node_type>::_S_equals(__c, *__n) &&
_M_eq()(__k, this->_M_extract()(__n->_M_v()));
So, it's checking that the hash codes are equal (a quick and dirty check if you've already calculated the hashes) and the keys are equal (a potentially slower operation for e.g. a quality hash of long strings) before using the hint iterator. That's the only case in which it uses the hint. Imagine the bucket logically has some colliding elements chained off it with keys K1, K2, K3, K4 and your hint iterator is to K4 but you're trying to insert a duplicate with K2: as the iterators are forward only, you have to use _M_find_before_node(...) to reach colliding elements earlier in the chain than your hint points to. After the _M_find_before_node(...) you can scan from K1 forwards to see if the key to insert - K2 - is already present in the elements that collided at the bucket.
(The implementation could be improved by skipping the hash comparison when the key comparison is known to be cheap, but getting that condition right with type traits would be a bit of a pain - how do you know which key equality functions are cheap? Could assume so for small, standard layout, trivially copyable types or similar, at least when the unordered container is instantiated with the default std::equals<> comparison....).

Accessing adjacent elements of a map in c++

Suppose I have a float-integer map m:
m[1.23] = 3
m[1.25] = 34
m[2.65] = 54
m[3.12] = 51
Imagine that I know that there's a mapping between 2.65 and 54, but I don't know about any other mappings.
Is there any way to visit the adjacent mappings without iterating from the beginning or searching using the find function?
In other words: can I directly access the adjacent values by just knowing about a single mapping...such as m[2.65]=54?
UPDATE Perhaps a more important "point" than my answer, brought up by #MattMcNabb:
Floating point keys in std:map
Can I directly access the adjacent values by just knowing about a single mapping (m[2.65]=54)
Yes. std::map is an ordered collection; which is to say that if an operator< exists (more generally, std::less) for the key type you can expect it to have sorted access. In fact--you won't be able to make a map for a key type if it doesn't have this comparison operator available (unless you pass in a predicate function to perform this comparison in the template invocation)
Note there is also a std::unordered_map which is often preferable for cases where you don't need this property of being able to navigate quickly between "adjacent" map entries. However you will need to have std::hash defined in that case. You can still iterate it, but adjacency of items in the iteration won't have anything to do with the sort order of the keys.
UPDATE also due to #MattMcNabb
Is there any way to visit the adjacent mappings without iterating from the beginning or searching using the find function?
You allude to array notation, and the general answer here would be "not really". Which is to say there is no way of saying:
if (not m[2.65][-2]) {
std::cout << "no element 2 steps prior to m[2.65]";
} else {
std::cout << "the element 2 before m[2.65] is " << *m[2.65][-2];
}
While no such notational means exist, the beauty (and perhaps the horror) of C++ is that you could write an augmentation of map that did that. Though people would come after you with torches and pitchforks. Or maybe they'd give you cult status and put your book on the best seller list. It's a fine line--but before you even try, count the letters and sequential consonants in your last name and make sure it's a large number.
What you need to access the ordering is an iterator. And find will get you one; and all the flexibility that it affords.
If you only use the array notation to read or write from a std::map, it's essentially a less-capable convenience layer built above iterators. So unless you build your own class derived from map, you're going to be stuck with the limits of that layer. The notation provides no way to get information about adjacent values...nor does it let you test for whether a key is in the map or not. (With find you can do this by comparing the result of a lookup to end(m) if m is your map.)
Technically speaking, find gives you the same effect as you could get by walking through the iterators front-to-back or back-to-front and comparing, as they are sorted. But that would be slower if you're seeking arbitrary elements. All the containers have a kind of algorithmic complexity guarantee that you can read up on.
When dereferencing an iterator, you will receive a pair whose first element is the key and second element is the value. The value will be mutable, but the key is constant. So you cannot find an element, then navigate to an adjacent element, and alter its key directly...just its value.

Boost.MultiIndex spatial operations

I needed a spatial map for an application. I found Boost.MultiIndex.
I followed its tutorial and understood how to create a type:
typedef boost::multi_index_container<MapNode,
indexed_by<
ordered_non_unique<member<MapNode, int, &MapNode::X>>,
ordered_non_unique<member<MapNode, int, &MapNode::Y>>
>
> Map_T;
And how to insert to it:
Map.insert(Node);
How do I retrieve a value based on its x and y coordinates? and how do I check if there is a value there?
First of all, you do not need boost::multi_index to solve this problem. Simply overload operator< for your type MapNode and use std::set (resp. std::map if multiple nodes with identical coordinates can occur). Therby, operater< compares (e.g.) for x-values first. Iff they are equal, proceed comparing the y coordinate.
There is only one reason for using boost::multi_index: If different access methodes are required. For instance, if you want an additional "view" where the nodes are first sorted by y and than by x too.
However, the member approach of multi_index (as in your code above) is not a good idea. Use identity twice, but provide two different comparison functions. Details can be found in the boost docu.
Finally, all these approches may not be the best possible ones - depending on your application. Specialized data structures are e.g. described in the book "Computational geometry" by Berg et. al.
Unfortunaetlly, I do not know any free implementation of these algorithms...

Best sorting algorithm for case where many objects have "do-not-care" relationships to each other

I have an unusual sorting case that my googling has turned up little on. Here are the parameters:
1) Random access container. (C++ vector)
2) Generally small vector size (less than 32 objects)
3) Many objects have "do-not-care" relationships relative to each other, but they are not equal. (i.e. They don't care about which of them appears first in the final sorted vector, but they may compare differently to other objects.) To put it a third way (if it's still unclear), the comparison function for 2 objects can return 3 results: "order is correct," "order need to be fliped," or "do not care."
4) Equalities are possible, but will be very rare. (But this would probably just be treated like any other "do-not-care."
5) Comparison operator is far more expensive than object movement.
6) There is no comparison speed difference for determining that objects care or don't care about each other. (i.e. I don't know of a way to make a quicker comparison that simply says whether the 2 objects care about each other of not.)
7) Random starting order.
Whatever you're going to do, given your conditions I'd make sure you draw up a big pile of tests cases (eg get a few datasets and shuffle them a few thousand times) as I suspect it'd be easy to choose a sort that fails to meet your requirements.
The "do not care" is tricky as most sort algorithms depend on a strict ordering of the sort value - if A is 'less than or equal to' B, and B is 'less than or equal to' C, then it assumes that A is less than or equal to C -- in your case if A 'doesn't care' about B but does care about C, but B is less than C, then what do you return for the A-B comparison to ensure A will be compared to C?
For this reason, and it being small vectors, I'd recommend NOT using any of the built in methods as I think you'll get the wrong answers, instead I'd build a custom insertion sort.
Start with an empty target vector, insert first item, then for each subsequent item scan the array looking for the bounds of where it can be inserted (ie ignoring the 'do not cares', find the last item it must go after and the first it must go before) and insert it in the middle of that gap, moving everything else along the target vector (ie it grows by one entry each time).
[If the comparison operation is particularly expensive, you might do better to start in the middle and scan in one direction until you hit one bound, then choose whether the other bound is found moving from that bound, or the mid point... this would probably reduce the number of comparisons, but from reading what you say about your requirements you couldn't, say, use a binary search to find the right place to insert each entry]
Yes, this is basically O(n^2), but for a small array this shouldn't matter, and you can prove that the answers are right. You can then see if any other sorts do better, but unless you can return a proper ordering for any given pair then you'll get weird results...
You can't make the sorting with "don't care", it is likely to mess with the order of elemets. Example:
list = {A, B, C};
where:
A dont care B
B > C
A < C
So even with the don't care between A and B, B has to be greater than A, or one of those will be false: B > C or A < C. If it will never happen, then you need to treat them as equals instead of the don't care.
What you have there is a "partial order".
If you have an easy way to figure out the objects where the order is not "don't care" for a given objects, you can tackle this with basic topological sorting.
If you have a lot of "don't care"s (i.e. if you only have a sub-quadratic number of edges in your partial ordering graph), this will be a lot faster than ordinary sorting - however, if you don't the algorithm will be quadratic!
I believe a selection sort will work without modification, if you treat the "do-not-care" result as equal. Of course, the performance leaves something to be desired.