2

I'm holding a map sorted on std::pair<K, V>. (It's type is std::map<std::pair<K, V>, size_t>). I want to find ANY pair with given first coordinate (i.e. with K fixed, find if there is any object in map, with key of form std::pair<K, _>, I don't care about the second coordinate). Obviously it can be done in O(log n), as searching specific pair is also done in O(log n) [that's standard find() operation]. Is there some way to do that without having to write my own map from scratch?

One more thing - I can't change comparing function, as I want pairs like (1,2), (1,3) to be different, and if comparator compares keys only, it will treat them as equals. I want to preserve standard find() operation, as I need to use it as well.

The solution from Finding any element with specific first coordinate in set<pair> > will not work as I have only guarantee that operator < is provided for both K and V. I do not know if std::numeric_limits is specialized for K

Community
  • 1
  • 1
qiubit
  • 4,708
  • 6
  • 23
  • 37
  • Generic types (it's template class) – qiubit Jan 05 '16 at 13:46
  • I have only guarantee that operator < is provided for both K and V – qiubit Jan 05 '16 at 13:46
  • 1
    If you allowed C++14, you might get more interesting answers involving is_transparent. – Marc Glisse Jan 05 '16 at 14:06
  • I voted to reopen your question as you said you do not know if you can get a minimum value. I also edit your question to explain that. Feel free to edit if you do not like it. – NathanOliver Jan 05 '16 at 14:07
  • 2
    You can replace the numeric_limits value with any value for V (copy it from the first element for instance). Then you need to check both the output of lower_bound and the previous element, but the idea still works. – Marc Glisse Jan 05 '16 at 14:13

2 Answers2

2

If you need any value with key equal to x, use a dummy value for V. If it's default-constructible, you can just put V() as the second, dummy element of the key; else pick the value from the map (e.g. from the first element). Then search for lower_bound with that key and also look at the previous element:

auto it = my_container.lower_bound(std::make_pair(x, V()));
bool found;
if (it == my_container.end()) {
    found = false;
} else {
    found = it->first.first == x;
    if (!found && it != my_container.begin()) {
        it--;
        found = it->first.first == x;
    }
}
kfx
  • 8,136
  • 3
  • 28
  • 52
0

I suggest breaking up the map into two maps:

multimap<K, map<V, size_t>>

And performing the pair construction/deconstruction using make_pair and get.

Also consider using unordered_multimap/unordered_map for the outer/inner maps if you don't need the order preserved.

gen-y-s
  • 871
  • 6
  • 12