0

Possibly related : [ Unordered-MultiMap of Pairs, C++ unordered_map using a custom class type as the key ]

I would like to use a pair of order-less strings as the key for my unordered_map.

For example I would like key1 to be the same as key2

key1 = {"john", "doe"}; key2 = {"doe", "john"};

Maybe I am missing something really silly here.

Here is my test code (doesn't work as I would want it to):

struct Key { std::string first; std::string second; Key(std::string a, std::string b) { first = a; second = b; } bool operator==(const Key k) const { return ((first == k.first && second == k.second) || (first == k.second && second == k.first)); } }; struct KeyHash { std::size_t operator()(const Key& k) const { return std::hash<std::string>()(k.first) ^ (std::hash<std::string>()(k.second) << 1); } }; struct KeyEqual { bool operator()(const Key& lhs, const Key& rhs) const { //return (lhs.first == rhs.first && lhs.second == rhs.second); // not this return ((lhs.first == rhs.first && lhs.second == rhs.second) || (lhs.first == rhs.second && lhs.second == rhs.first)); } }; void test_unorderedMap() { Key s1("John", "Doe"); Key s2("Doe", "John"); Key s3("Mary", "Sue"); Key s4("Sue", "Mary"); // first attempt std::unordered_map<Key, std::string, KeyHash> m1; m1[s1] = "a"; m1[s2] = "b"; m1[s3] = "c"; m1[s4] = "d"; std::cout << "m6[s1] : " << m1.find(s1)->second << std::endl; // prints .. a std::cout << "m6[s2] : " << m1.find(s2)->second << std::endl; // prints .. b std::cout << "m6[s3] : " << m1.find(s3)->second << std::endl; // prints .. c std::cout << "m6[s4] : " << m1.find(s4)->second << std::endl; // prints .. d // second attempt std::unordered_map<Key, std::string, KeyHash, KeyEqual> m2; m2[s1] = "a"; m2[s2] = "b"; m2[s3] = "c"; m2[s4] = "d"; std::cout << "m2[s1] : " << m2.find(s1)->second << std::endl; // prints .. a std::cout << "m2[s2] : " << m2.find(s2)->second << std::endl; // prints .. b std::cout << "m2[s3] : " << m2.find(s3)->second << std::endl; // prints .. c std::cout << "m2[s4] : " << m2.find(s4)->second << std::endl; // prints .. d } 

1 Answer 1

1

For identical objects, a hash must always be equal. So if you consider these to instances equal:

Key s1("John", "Doe"); Key s2("Doe", "John"); 

You must also make sure the hash of both is identical. To do that, you could for example first sort both strings and create a hash based on the sorted strings.

Sign up to request clarification or add additional context in comments.

2 Comments

or you could xor in your hashfunction without the shifting. That is probably easier.
I suspected the same. Thank you very much for helping me confirm my thoughts.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.