Mapping different keys to the same value in c++ - c++

So I searched around and found that we can use multi-map to map a set of equivalent keys to different values. I am wondering how to do the reverse? That is to map different keys to the same value? Is there a stl data structure for that?

A normal std::map (or std::unordered_map) can do that. You have a few choices on how to do that:
Normal key-value store, where you copy the values as needed
Normal key-value store, but where the value is a pointer to the actual data that can be shared, optionally using a std::shared_ptr
Use some kind of structure (a std::tuple perhaps) to collect the keys (though it's probably more trouble handling this than it's worth, nothing I really recommend)
Use Boost multi-index containers
With Boost you have a ready solution that you can just use, and if you already use Boost in your project (it is a great set of libraries, and complements the standard library well) I think it's a no-brainer to pick that solution.

You can have a std::map such that multiple keys map to the same value. There is nothing against that. However, what you are probably looking for is the ability to to find all the keys that map to a given value without iterating over the entire map. I don't think there is any such data structure for that.

Related

Is there a data structure that works like a map but also allows the sequence of values to be used independently of the keys?

Often I have a map for which the keys are only used for importing, exporting and setup. During the performance critical stage, the values are of importance, not the keys.
I would like to use a data structure that acts like a map but gives me the option to just use a simple std::vector of mapped values when the keys are irrelevant.
The implementation seems reasonably simple. Just use a pair of equally sized vectors in which to store the key and value respectively, sorted with respect to the key vector. Insertions and deletions will be less efficient than in boost::flat_map, but that is a compromise I'm willing to make in order to get instant access to the vector of key unencumbered values.
Is this a terrible idea? If not, is there an existing implementation I can use?

C++ multi-index map implementation

I'm implementing a multi-index map in C++11, which I want to be optimized for specific features. The problem I'm currently trying to solve, is to not store key elements more then once. But let me explain.
The problem arose from sorting histograms to overlay them in different combinations. The histograms had names, which could be split into tokens (properties).
Here are the features I want my property map to have:
Be able to loop over properties in any order;
Be able to return container with unique values for each property;
Accumulate properties' values in the order they arrive, but to be able to sort properties using a custom comparison operator after the map is filled;
I have a working implementation in C++11 using std::unordered_map with std::tuple as key_type. I'm accumulating property values as they arrive into a tuple of forward_lists. The intended use, is to iterate over the lists to compose keys.
The optimization I would like to introduce, is to only store properties' value in the lists, and not store them in tuples used as keys in the map. I'd like to maintain ability to have functions returning const references to lists of property values, instead of lists of some wrappers.
I know that boost::multi_index has similar functionality, but I don't need the overhead of sorting as the keys arrive. I'd like to have new property values stored sequentially, and only be sortable postfactum. I've also looked at boost::flyweight, but in the simplest approach, the lists will then be of flyweight<T> instead of T, and I'd like to not do that. (If that IS the best solution, I could definitely live with it.)
I know that lists are stable, i.e. once an element is created, its pointer and iterator remain valid, even after invoking list::sort(). Knowing that, can something be done to the map, to eliminate redundant copies of tuple elements? Could a custom map allocator help here?
Thanks for suggestions.
Have your map be from tuples of iterators to your prop containers.
Write a hash the dereferences the iterators and combines the result.
Replace the forward list prop containers with sets that first order on hash, then contents.
Do lookup by first finding in set, then doing lookup in hash.
If you need a different order for props, have another container of set iterators.

Associative container with queue-like properties on the values

I have data in the form of instances of a POD struct. Under "normal" conditions, I need to access them via a unique ID, currently via a std::map. If something goes wrong, however, I need to traverse the data in an order provided by a specific member of the POD struct.
I don't want to copy all data sets of the map to a priority queue in case of error -- this seems much to expensive.
I tried running std::make_heap on the std::map, but that doesn't even compile, because the map's iterators cannot be subtracted.
The sort keys will change on a regular basis, so keeping the data in a priority queue and just storing pointers in the map seems not to be feasible, especially as access via the map (the typical use-case) becomes more expensive by the indirection.
The other way around, i.e. storing pointers in a separate data structure that can be heapified on demand seems feasible, but the synchronization might be error-prone.
Is there anything in the std libraries, boost or tbb that would accomplish what I want?
It looks like this is a work for the Boost Multi-Index Containters Library.

Which is the fastest STL container for find?

Alright as a preface I have a need to cache a relatively small subset of rarely modified data to avoid querying the database as frequently for performance reasons. This data is heavily used in a read-only sense as it is referenced often by a much larger set of data in other tables.
I've written a class which will have the ability to store basically the entirety of the two tables in question in memory while listening for commit changes in conjunction with a thread safe callback mechanism for updating the cached objects.
My current implementation has two std::vectors one for the elements of each table. The class provides both access to the entirety of each vector as well as convenience methods for searching for a specific element of table data via std::find, std::find_if, etc.
Does anyone know if using std::list, std::set, or std::map over std::vector for searching would be preferable? Most of the time that is what will be requested of these containers after populating once from the database when a new connection is made.
I'm also open to using C++0x features supported by VS2010 or Boost.
For searching a particular value, with std::set and std::map it takes O(log N) time, while with the other two it takes O(N) time; So, std::set or std::map are probably better. Since you have access to C++0x, you could also use std::unordered_set or std::unordered_map which take constant time on average.
For find_if, there's little difference between them, because it takes an arbitrary predicate and containers cannot optimize arbitrarily, of course.
However if you will be calling find_if frequently with a certain predicate, you can optimize yourself: use a std::map or std::set with a custom comparator or special keys and use find instead.
A sorted vector using std::lower_bound can be just as fast as std::set if you're not updating very often; they're both O(log n). It's worth trying both to see which is better for your own situation.
Since from your (extended) requirements you need to search on multiple fields, I would point you to Boost.MultiIndex.
This Boost library lets you build one container (with only one exemplary of each element it contains) and index it over an arbitrary number of indices. It also lets you precise which indices to use.
To determine the kind of index to use, you'll need extensive benchmarks. 500 is a relatively low number of entries, so constant factors won't play nicely. Furthermore, there can be a noticeable difference between single-thread and multi-thread usage (most hash-table implementations can collapse on MT usage because they do not use linear-rehashing, and thus a single thread ends up rehashing the table, blocking all others).
I would recommend a sorted index (skip-list like, if possible) to accomodate range requests (all names beginning by Abc ?) if the performance difference is either unnoticeable or simply does not matter.
If you only want to search for distinct values, one specific column in the table, then std::hash is fastest.
If you want to be able to search using several different predicates, you will need some kind of index structure. It can be implemented by extending your current vector based approach with several hash tables or maps, one for each field to search for, where the value is either an index into the vector, or a direct pointer to the element in the vector.
Going further, if you want to be able to search for ranges, such as all occasions having a date in July you need an ordered data structure, where you can extract a range.
Not an answer per se, but be sure to use a typedef to refer to the container type you do use, something like typedef std::vector< itemtype > data_table_cache; Then use your typedef type everywhere.

Which STL container for ordered data with key-based access?

Let's say I have a collection of Person objects, each of which looks like this:
class Person
{
string Name;
string UniqueID;
}
Now, the objects must be stored in a container which allows me to order them so that I can given item X easily locate item X+1 and X-1.
However, I also need fast access based on the UniqueID, as the collection will be large and a linear search won't cut it.
My current 'solution' is to use a std::list in conjunction with a std::map. The list holds the Persons (for ordered access) and the map is used to map UniqueID to a reference to the list item. Updating the 'container' typically involves updating both map and list.
It works, but I feel there should be a smarter way of doing it, maybe boost:bimap. Suggestions?
EDIT: There's some confusion about my requirement for "ordering". To explain, the objects are streamed in sequentially from a file, and the 'order' of items in the container should match the file order. The order is unrelated to the IDs.
boost:bimap is the most obvious choice. bimap is based on boost::multi_index, but bimap has simplified syntax. Personally I will prefer boost::multi_index over boost::bimap because it will allow to easily add more indices to the Person structure in the future.
There is no Standard Library container that does what you want - so you will have to use two containers or the Boost solution. If using two containers, I would normally prefer a vector or a deque over a list, in almost all circumstances.
Why not to use two maps , one having Person as Key and another one having UniqueId as Key, but that requires updating both of them.
you can create a callback function which updates both the maps whenever there is any change.