std::map one key, two values - c++

What is the best way to map two values to one key?
ie An item with a value and bool.
Tried using:
std::map<std::string, std::pair<std::string, bool> > myMap2
But that doesn't seem like the correct solution. Is there a more elegant way to do this?

That is indeed the correct solution. More generally, consider using std::tuple instead of std::pair for a uniform interface regardless of the number of values (as std::pair is obviously restricted to two), or boost::tuple if your compiler is too old to ship with a std:: or std::tr1:: implementation.

Either use std::pair<> as you did, or make a custom struct containing the values you want to store. I'd do the latter in most cases, as the values then have names more descriptive than first and second.

Normally, I crate a simple mapValue struct/class.

Related

C++ get keywords of map

As far as I looked through the C++ reference, there is no function which returns a vector (or similar) containing all the keywords of a map. Why is this so? This is not a super important function, but sometimes it can be useful. (I don't exactly understand the key_comp function, but this seems to be not what I'm looking for)
Just for completeness, here is some function which does what I want:
template<typename key_t, typename value_t>
std::vector<key_t> getKeywords(const std::map<key_t, value_t>& m){
std::vector<key_t> keywords;
for(const auto& it: m){
keywords.push_back(it.first);
}
return keywords;
}
This is for the same reason that there is no operator+ for std::list iterators.
The standard tries not to encourage inefficient operations, in preference for you choosing the appropriate container for the job.
Creating a vector of all map keys is non-trivial because such a vector is not maintained internally along with the map.
You can of course create it if you really want, as you've already shown. But the standard wants you to know that you probably should be looking for another approach.
For example, if you just want to iterate over the keys, you can iterate over the whole map instead and use only the first part of each resultant pair.
Also, the standard library is intended to give you building blocks, not to suit every possible use case imaginable.
The two chief reasons are that most implementations do not have a vector of keywords intenally, so they would have to create it on the fly. And as you can see, creating it isn't really hard so there is little need to have it in the Standard,
Indeed, the keys are not accessible as such because the concern of the map class is O(log(N)) retrieval, not iteration.
As a general guideline when using the stl, choose your containers according to the use case of your application. If you want fast iteration, you can use a vector of tuple<Key, Value> and sort it, or use a pair<vector<Key>, vector<Value>> that you keep sorted by hand. std::make_heap and the like can be handy for this approach.
Retrieving the map keys can be done like your implementation.

C++ feature, like std::set, which allows duplicates

I have an std::set, which stores std::pairs of two integers. The std::set is also sorted, by allowing me to pass a helping class. However, I have written many lines of code so far and now, at the last tests, "they" told me something, that actually means that I need to allow possible duplicates in the std::set. Of course this isn't done with std::set. Any alternative that will not make me change the whole-big project?
In short, I use the std::set as an ordered list with data an std::pair of two ints.
You can use std::multiset. That should work for what you are describing.
std::multiset is the answer, as suggested by WhozCraig.

How to sort massive map by one value property?

I have a map<std::string, myStruct> I wonder how to sort items in map by int property that is in myStruct.order and if 2 or more of myStruct orders are same throw list of keys (strings) that make map unsortable by that field of myStruct? Is there any fancy way of doing in in C++03 (may be with boost)?
boost has a complete (and complex) functionality in MultiIndex, but if I understand your requirements, it's overkill in this case. A fairly easy way could be to build a list of pointers to myStruct and sort. Then you can easily check for duplicate keys (these became adjacents).
sort should use a functor of type less<const myStruct*>, i.e.
bool compare_orders(const myStruct* a, const myStruct* b) { return a->order < b->order; }
What meaning is there in "sorting" a map? Sure, the map may be internally organized as a BST or something to make access faster, but conceptionally the elements of the map are in no particular order.
Other than that, you CAN supply an ordering method for the keys (because even if you do organize the map in a particular way, it is by the order of the keys, not by that of the values), but not for the values with the third template argument for map.
You can't do this, using std::map - the first in the pair is used for comparing (it's called key). In your case, thestd::string is the key.
You can use std::set< std::pair< std::string, MyStruct > > and then implement operator< for two std::pair< std::string, MyStruct >-s.
Or, you can change the std::map's definition, if it's possible/allowed/suitable/etc. It really depends on what you're trying to do and what you're allowed to do.
Or some other container (that keeps the order of elements, as inserted - like std::list, std::vector, etc.), and then using std::sort or container's sort method, if exists.
I agree with the other answers that it's not clear why you need to sort the map. But you can use a bidirectional map to let you view both myStruct and string as keys.
There's one in boost:
http://www.boost.org/doc/libs/1_48_0/libs/bimap/doc/html/index.html
There's an example here
http://www.boost.org/doc/libs/1_48_0/libs/bimap/doc/html/boost_bimap/examples/simple_bimap.html

Boost::Multiindex vs string indexed boost::unordered_map

I need a container of unique elements to be accessed with a triplet of int, and each int can be over 1.000.000.000.
(Only few of these elements will be actually filled, and actually these elements are boost::unordered_map themselves).
Is it faster to have a multiindex array like boost::multiindex (or maybe something else I don't know) or just a boost::unordered_map with a composed string as a key ?
Multi-index isn't what you want, you seem to want a single index whose type is a triple. (Unless you actually do want three independent indexes; if I misunderstood, leave a comment.)
Don't use strings, heavens no. Just use the triple as a key:
typedef std::tuple<int, int, int> key_type;
If you use an std::map<key_type, T>, you get logarithmic lookup, which may be sufficient, and I think you don't even have to do any more work (not sure if lexicographic comparison is defined by default for tuples).
If you want to use an std::unordered_map<key_type, T> (or the boost version), you have to define a hash function. Boost already has one for tuples, I think, but C++11 doesn't; but it's very easy to implement yourself based on hash_combine() which you can just crop out off the Boost code.

Is it possible to use a custom class in place of std::pair in an STL map?

Is this possible?
#include <map>
class Example {
private:
std::map<std::string, std::string, less<std::string>,
std::allocator< CustomPair<std::string, std::string> > > myMap;
};
In the example above, CustomPair would be a template class holding a key and value. If this is possible, is it that simple or is there anything I should look out for?
One can only speculate what your real intent is here, so I assume you already have a class that contains both key and value. In that case std::set with a custom comparison may be a better choice than a std::map.
You then need to provide a comparison that will only compare the key part of your class and the key part must be const (not change over time) as long as the object is in the set.
As mentioned in the comment the elements of a set are only accessable as consts, so if you want to change the value of a such element you need to const_cast the write access or declare the member mutable.
In another answer iain made another very good suggestion. If you rarely insert into the container and mostly access the container searching for elements then a sorted std::vector and std::binary_search are a very effective alternative to the set.
I would be more likely to use std::set.
I would either use a set as described by lothar or use an sorted std::vector as described in "Effective STL" chapter 23: "Consider replacing associative containers with sorted vectors".
The rational for this is that a std::binary_search of a sorted vector with a custom comparitor is nearly as fast and sometimes faster than a map lookup and iteration is much faster. The insert operations are more expensive though (you have to call sort after each insert). A lot of map use cases insert very infrequently though.
The vector would be more flexibility than the set.
I replaced a map of 2000 complex objects (indexed by int) with this approach, iteration and processing every object in the map went from 50 seconds to less than 5 on a server class system. There was no noticeable difference for map lookups times.
I think you can do it but will not get the desired effect, because the use of std::allocator will be done via rebind<std::pair>, thus overriding your selection of CustomPair. In fact, it probably doesn't matter what type you put there, the STL functions will ignore it. At least some of them will definitely do this, but I'm not sure all will. Strictly speaking this is almost certainly implementation dependent. I don't know what the standard says.