1

I have a map of data; the key is std::string. I want to perform a binary search on it, but I cannot just use std::map::find(), because I will provide only a part of the key.

Let's say I have a map with the following keys:

["abc"] -> ...
["efg"] -> ...
["ijk"] -> ...
["iik"] -> ...

I want to search through this with, let's say providing only "i", and the search should return:

["ijk"] -> ..., ["iik"] -> ...

Is this possible? I have tried to do this using iterators, but I failed, as I cannot treat them as indexes.

Note: I keep the data in a map, because of other reasons, so I don't want to change it into a different data structure.

honk
  • 9,137
  • 11
  • 75
  • 83
khajvah
  • 4,889
  • 9
  • 41
  • 63

3 Answers3

5

It's possible, but you wouldn't need to actually binary-search through the data.

You can use lower_bound to find the first element and then advance the resulting iterator until your key no longer matches your criteria, storing them in a <vector> or similar container to return them all.

lccarrasco
  • 2,031
  • 1
  • 17
  • 20
3

map::lower_bound() will help you here.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
0

I built a solution based on map::lower_bound() as suggested by lccarrasco and Michael Burr. This function provides an iterator to the first element in your map you are looking for. The function performs a binary search as its complexity is logarithmic in size.

Then you have to advance the provided iterator as long as the string you are looking for is a prefix of the values in your map. One way of doing this is using string::compare().

For the sake of clarity I have chosen int as value of your map. Please replace it with the type of your data. All in all the code looks as follows:

int main() {
    std::map <std::string, int> myMap{ {"abc", 1}, {"efg", 2}, {"ijk", 3}, {"iik", 4} };
    std::string prefix("i");

    for (auto it = myMap.lower_bound(prefix); it != std::end(myMap) && it->first.compare(0, prefix.size(), prefix) == 0; ++it)
        std::cout << it->first << " -> " << it->second << std::endl;

    return 0;
}

Output:

iik -> 4
ijk -> 3

Code on Ideone

honk
  • 9,137
  • 11
  • 75
  • 83