2

I need a data container for collecting numeric data based on one or multiple keys (like a key built of int and std::string).

For one key, I simply can use unordered_map<std::string, int> respectively unordered_map<std::string, List<int>> if multiple values should be collected.

What about having multiple keys? Other posts suggested me to use std::make_pair<type1, type2> as key, but this only works for 2 keys and looks a little hacky.

Is there any easy-to-use data structure or library allowing keys built of multiple variables and multiple values assigned to it? The values only must be accessible by the keys (I do not need something like boost::multi_index which provides several interfaces to access values). Furthermore the values must not be sorted in the container, however fast access is desired as the values are added/incremented during data processing.

max66
  • 65,235
  • 10
  • 71
  • 111
Patrick
  • 1,046
  • 2
  • 10
  • 31
  • Eventually use a `std::tuple` for more than one key value? I don't know if this would be possible. – πάντα ῥεῖ Sep 27 '16 at 08:09
  • 4
    Creating a struct with the multiple members and using it as a key will work just fine as long as the needed operator(s) are overloaded. – Hatted Rooster Sep 27 '16 at 08:10
  • @GillBates I think in case of unordered collections apart from equality operator std::hash should also be specialized... – W.F. Sep 27 '16 at 08:33
  • Stupid question (or not): "multiple" in sense "composite key", or "multiple" in sense "any of multiple keys point one data" – Jacek Cz Sep 27 '16 at 08:35
  • @W.F. Very sp00ky indeed. – Hatted Rooster Sep 27 '16 at 08:36
  • @JacekCz Multiple in sense of a "composite key". Like a primary key in a DB built of multiple fields. – Patrick Sep 27 '16 at 08:36
  • @GillBates I used a struct but I receive an error, is it possible that I have to implement a hash function? How could it look like for the struct consisting of a std::string and int value? – Patrick Sep 27 '16 at 08:37
  • @Patrick because You write "based on one or multiple keys ". Sorry for time waste – Jacek Cz Sep 27 '16 at 08:38
  • 1
    @Patrick http://stackoverflow.com/a/17017281/1870760 shows you everything you need to know, just combine the two members with `std::hash`. – Hatted Rooster Sep 27 '16 at 08:39
  • @Patrick here's comes a problem... I'm not sure if one even can specialize `std::hash` to types that are built-in or implemented in `std::` namespace without risk of undefined behaviour... – W.F. Sep 27 '16 at 08:39
  • @W.F. Yes you can, easily, check the link. – Hatted Rooster Sep 27 '16 at 08:42
  • @GillBates well I'm not saying that you can't I'm saying that it may cause UB as long as you are specializing for built-in type or the type from `std::` namespace... – W.F. Sep 27 '16 at 08:43
  • @W.F. There is absolutely no risk. I don't get why you would think that. – Hatted Rooster Sep 27 '16 at 08:44
  • @GillBates http://en.cppreference.com/w/cpp/language/extending_std – W.F. Sep 27 '16 at 08:49
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/124271/discussion-between-gill-bates-and-w-f). – Hatted Rooster Sep 27 '16 at 08:50

1 Answers1

3

You can use std::tuple for the same. Tuple Comparison works for multiple elements of almost all built in types. for example

typedef tuple<int, int> tx;
tx t1 = make_tuple(1, 1);
tx t2 = make_tuple(1, 2);

if (t1 == t2) {
        cout << "EQUAL" << endl;
}

or

typedef tuple<string, string> tx;
    tx t1 = make_tuple("AB", "CD");
    tx t2 = make_tuple("AB", "CD");

    if (t1 == t2) {
        cout << "EQUAL" << endl;
    }

Use the tuple as the key in you unordered_map

An example of using map could be

map<tx, int> mp;
mp[make_tuple("AB", "CD")] = 100;
mp[make_tuple("EF", "GH")] = 200;

To Update an existing Key, we can use

mp[t1] = 300;
Daksh Gupta
  • 7,554
  • 2
  • 25
  • 36
  • I tried it with tuple and it requires to implement a hash function. So basically the same effort is required as by using a struct instead? – Patrick Sep 27 '16 at 08:46
  • No You dont, you can write a map like this. – Daksh Gupta Sep 27 '16 at 10:17
  • typedef tuple tx; tx t1 = make_tuple("AB", "CD"); tx t2 = make_tuple("AB", "CD"); if (t1 == t2) { cout << "EQUAL" << endl; } map mp; mp[make_tuple("AB", "CD")] = 100; mp[make_tuple("EF", "GH")] = 200; mp[t1] = 300; – Daksh Gupta Sep 27 '16 at 10:17
  • Thanks for additional explanation! I think that tuples have the advantage of not having to implement any hash and comparison function, but if many parameters are used, structs are more comprehensible. – Patrick Sep 29 '16 at 14:53