Std:: map частичное совпадение ключа
У меня есть std:: map, и я хочу искать ключ, используя подстроку. Для примера
#include <iostream>
#include <map>
#include <string>
using namespace std;
typedef std::map<std::string, std::string> TStrStrMap;
typedef std::pair<std::string, std::string> TStrStrPair;
int main(int argc, char *argv[])
{
TStrStrMap tMap;
tMap.insert(TStrStrPair("John", "AA"));
tMap.insert(TStrStrPair("Mary", "BBB"));
tMap.insert(TStrStrPair("Mother", "A"));
tMap.insert(TStrStrPair("Marlon", "C"));
return 0;
}
Я хочу найти позицию, которая содержит подстроку "Marl", а не "Marlon". Является ли это возможным? Как?
РЕДАКТИРОВАТЬ: нет библиотек boost!
Ответы
Ответ 1
Вы не можете эффективно искать подстроку, но можете использовать префикс:
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
typedef map<string, string> TStrStrMap;
typedef pair<string, string> TStrStrPair;
TStrStrMap::const_iterator FindPrefix(const TStrStrMap& map, const string& search_for) {
TStrStrMap::const_iterator i = map.lower_bound(search_for);
if (i != map.end()) {
const string& key = i->first;
if (key.compare(0, search_for.size(), search_for) == 0) // Really a prefix?
return i;
}
return map.end();
}
void Test(const TStrStrMap& map, const string& search_for) {
cout << search_for;
auto i = FindPrefix(map, search_for);
if (i != map.end())
cout << '\t' << i->first << ", " << i->second;
cout << endl;
}
int main(int argc, char *argv[])
{
TStrStrMap tMap;
tMap.insert(TStrStrPair("John", "AA"));
tMap.insert(TStrStrPair("Mary", "BBB"));
tMap.insert(TStrStrPair("Mother", "A"));
tMap.insert(TStrStrPair("Marlon", "C"));
Test(tMap, "Marl");
Test(tMap, "Mo");
Test(tMap, "ther");
Test(tMap, "Mad");
Test(tMap, "Mom");
Test(tMap, "Perr");
Test(tMap, "Jo");
return 0;
}
Отпечатки:
Marl Marlon, C
Mo Mother, A
ther
Mad
Mom
Perr
Jo John, AA
Ответ 2
Когда ваша подстрока является префиксом, как в вашем примере, вы можете использовать lower_bound
для поиска "Marl"
.
map<string,string>::const_iterator m = tMap.lower_bound("Marl");
cerr << (*m).second << endl;
Это не работает для подстрок без префикса: в общем случае поиск карты не сильно отличается от поиска в других контейнерах.
Ответ 3
Чтобы найти подстроку ключа на карте, у вас нет выбора, кроме как использовать новую карту по типу особого типа или для поиска вашей карты в O (n). std::map
использует (по умолчанию) operator<()
для упорядочения ключей и поиска, а функция сравнения для std::string
- это простой лексикографический счёт.
Если вы создаете новую карту по специальному типу ключа, который имеет operator<()
compare на основе подстроки, обратите внимание, что это также повлияет на решение о том, будет ли новый элемент вставляться в дубликат. Другими словами, такая карта будет иметь только элементы, которые не являются подстроками друг друга.
Поиск O (n) практически означает, что вы используете std::find()
по карте с пользовательским предикатом, который принимает std::pair<std::string,std::string>
и возвращает true, если второй элемент пары является подстрокой первого.
Ответ 4
typedef TStrStrMap::value_type map_value_type;
struct key_contains_substring
: std::binary_function<map_value_type, std::string, bool>
{
bool operator()(const map_value_type& map_value, const std::string& substr)
{
return std::search(map_value.first.begin(), map_value.first.end(),
substr.begin(), substr.end() != map_value.first.end());
}
};
...
TStrStrMap::const_iterator it = std::find_if(tMap.begin(), tMap.end(),
std::bind2nd(key_contains_substring(), "Marl");