c++ - finding wildcard entries efficiently -


i have map contains strings keys; string resemble wildcards.

a key can have * @ end, means when lookup performed, string has key prefix shall match key.

how can efficiently retrieve closest matching entry in such map?

i tried sorting map entries in custom way , using lower_bound, sorting not produce correct result:

#include <map> #include <string> #include <iostream> #include <algorithm>  struct compare {     bool operator()(const std::string& lhs, const std::string& rhs) const     {         if (lhs.size() < rhs.size()) {             return true;         }          if (lhs.size() > rhs.size()) {             return false;         }          bool iswildcardlhsatend = (!lhs.empty() && lhs.back() == '*');         bool iswildcardrhsatend = (!rhs.empty() && rhs.back() == '*');          if (iswildcardlhsatend && iswildcardrhsatend) {             return lhs < rhs;         }         auto lhsubstring = lhs.substr(0, lhs.size() - 1);         auto rhssubstring = rhs.substr(0, rhs.size() - 1);          if (iswildcardlhsatend || iswildcardrhsatend) {             if (lhsubstring == rhssubstring) {                 return !iswildcardlhsatend;             }             else {                 return lhsubstring < rhssubstring;             }         }          return lhs < rhs;     } };  template <typename map> void lookup(const map& map, const std::string& key, int expected) {     auto = map.lower_bound(key);     if (it != map.end()) {         std::cout << "found " << it->first << " " << key << "; ";         std::cout << "expected: " << expected << " got: " << it->second << std::endl;     }     else {         std::cout << "did not find match " << key << std::endl;     } }  int main() {     std::map<std::string, int, compare> map = {         { "bar", 1 },         { "bar*", 2 },         { "foo1", 3 },         { "bar1", 4 },         { "bar1*", 5 },         { "foo1*", 6 },         { "bar12", 7 },         { "bar12*", 8 },         { "foo12", 9 },         { "bar123", 10 },         { "b*", 11 },         { "f*", 12 },         { "b", 13 },         { "f", 14 }     };      std::cout << "sorted map \n------" << std::endl;     std::for_each(map.begin(), map.end(), [](const auto& e) { std::cout << e.first << std::endl; });     std::cout << "-------" << std::endl;      lookup(map, "foo1", 3);     lookup(map, "foo123", 6);     lookup(map, "foo", 12);     lookup(map, "bar1234", 8); } 

this produces following output demonstrates incorrect lookup:

sorted map  ------ b f b* f* bar bar1 bar* foo1 bar12 bar1* foo12 foo1* bar123 bar12* ------- found foo1 foo1; expected: 3 got: 3 did not find match foo123 found bar1 foo; expected: 12 got: 4 did not find match bar1234 

live example

i open using data structure if necessary.

if separate exact search , wildcard search, natural ordering works fine strings. code seems produce desired results (i think), , efficient. separate maps can wrapped more conveniently of course.

#include <map> #include <string> #include <iostream> #include <algorithm> template <typename map> void lookup(const map& exact ,const map& wilds, const std::string& key, int expected) {     auto = exact.find(key);      if (it == exact.end()) {    // if not exact match            = wilds.lower_bound(key);    // best match          it--;      }          std::cout << "found " << it->first << " " << key << "; ";         std::cout << "expected: " << expected << " got: " << it->second << std::endl; }  int main() {     std::map<std::string, int> wilds = {         { "bar*", 2 },         { "bar1*", 5 },         { "foo1*", 6 },         { "bar12*", 8 },         { "b*", 11 },         { "f*", 12 }     };     std::map<std::string, int> exact = {         { "bar", 1 },         { "foo1", 3 },         { "bar1", 4 },         { "bar12", 7 },         { "foo12", 9 },         { "bar123", 10 },         { "b", 13 },         { "f", 14 }     };     lookup(exact , wilds, "foo1", 3);     lookup(exact , wilds,"foo123", 6);     lookup(exact , wilds,"foo", 12);     lookup(exact , wilds,"bar1234", 8); } 

Comments

Popular posts from this blog

networking - Vagrant-provisioned VirtualBox VM is not reachable from Ubuntu host -

c# - ASP.NET Core - There is already an object named 'AspNetRoles' in the database -

ruby on rails - ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true -