我有一个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”的位置。可能吗?怎么样?
编辑:没有加速库!
答案 0 :(得分:22)
您无法有效地搜索子字符串,但您可以前缀:
#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
答案 1 :(得分:8)
当您的子字符串是前缀时,您可以使用lower_bound
搜索"Marl"
。
map<string,string>::const_iterator m = tMap.lower_bound("Marl");
cerr << (*m).second << endl;
这不适用于非前缀子串:在一般情况下,搜索地图与搜索其他容器没有太大区别。
答案 2 :(得分:2)
要在地图中搜索某个键的子字符串,您别无选择,只能在特殊类型的键类型上使用新地图,或者在O(n)中搜索地图。 std::map
使用(默认情况下)operator<()
来排序键和搜索,std::string
的比较函数是一个简单的词典比较。
如果在特殊键类型上创建一个新的映射,其中operator<()
基于子字符串进行比较,请注意这也会影响插入新元素是否重复的决定。换句话说,这样的地图只会包含彼此不是子串的元素。
O(n)搜索实际上意味着你在地图上使用std::find()
,自定义谓词采用std::pair<std::string,std::string>
并且如果该对的第二个元素是第一个的子串,则返回true
答案 3 :(得分:1)
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");
答案 4 :(得分:0)
我想通过使用answer by dasblinkenlight提供完整的解决方案来扩展map::lower_bound()
。如该答案的评论中所述,您必须检查i
是否返回lower_bound()
。如果不是,那么您还必须检查找到的关键字是否实际上以搜索字符串为前缀。可以使用for example来检查后string::compare()
。结果,我的C ++ 11解决方案如下所示:
tMap.end()
输出:
Marla:D
但是,如果要在地图中查找所有以搜索字符串作为前缀的键,则可以使用以下循环:
std::map<std::string, std::string> myMap{
{"John", "AA"}, {"Mary", "BBB"}, {"Mother", "A"}, {"Marlon", "C"}, {"Marla", "D"}
};
std::string prefix("Marl");
auto it = myMap.lower_bound(prefix);
if (it != std::end(myMap) && it->first.compare(0, prefix.size(), prefix) == 0)
std::cout << it->first << ": " << it->second << std::endl;
输出:
Marla:D
马龙:C