我正在尝试创建一个程序,该程序从.txt或类似文件中获取数据,并要求用户搜索要搜索的单词。输出应该在上下文中显示关键字,其中包含最初位于其前面的2个单词以及它后面的单词。 (EX:关键字:男孩会输出"男孩跑掉")我能够使用equal_range()函数在文件中找到关键字的所有实例,但是我不知道如何迭代地图中的数据用于访问上下文的其他单词。到目前为止,这是我的代码:
typedef multimap<string, int> templateMap;
templateMap wordMap;
typedef pair<templateMap::iterator, templateMap::iterator> searchTemplate;
searchTemplate search;
typedef pair<templateMap::const_iterator, templateMap::const_iterator> innerIteratorTemplate;
multimap<string, int>::iterator tempMap;
string tempWord;
string keyword;
// omitted code
for (size_t i = 0; !inData.eof(); i++)
{
inData >> tempWord;
wordMap.insert(pair<string, int>(tempWord, i));
}
search = wordMap.equal_range(keyword);
for (multimap<string, int>::iterator itr = search.first; itr != search.second; ++itr)
{
cout << "The keyword " << keyword << " is found at location " << itr->second << endl;
tempMap = itr;
itr->second = itr->second - 2;
cout << itr->first << endl;
}
我知道底部for循环中的代码是错误的,但它是出于测试目的。
答案 0 :(得分:0)
您需要双向查找:您需要将单词映射到其索引(这是wordMap
的用途),并且您需要将索引映射到其单词(这是您缺少的)。所以让我们补充一下,以及修复你的初始循环:
std::vector<std::string> words;
while (inData >> tempWord) {
wordMap.insert(std::make_pair(tempWord, words.size()));
words.push_back(tempWord);
}
现在,我们双向进行 - 因为words
允许按索引查找。因此,我们有:
for (auto const& pair : as_range(wordMap.equal_range(keyword))) {
for (size_t idx = pair.second - 2; idx < pair.second + 3; ++idx) {
std::cout << words[idx] << ' ';
}
std::cout << '\n';
}
as_range()
是一个需要一对迭代器的东西,它会为你提供一些可以在基于范围的表达式中使用的东西。这不考虑words
的范围(如果您选择前两个或前两个单词中的一个作为关键字),但这应该会让您走上正确的轨道。
此外,如果您总是要迭代所有值并且不需要迭代器稳定性,请考虑使用std::map<std::string, std::vector<size_t>>
而不是std::multimap<std::string, size_t>
。有关详细信息,请参阅this question。
答案 1 :(得分:0)
鉴于您的问题陈述,map
不合适,因为您立即丢失了所有位置信息,而您还是试图找到解决方法。如果您愿意将所有数据保存在容器中,您也可以将其保存在vector
中并执行线性搜索。是的,我知道,理论上 会慢一点,但它很难在实践中获胜......
对于咯咯笑,这里采用<regex>
设施完全不同的方法:
// Data.
string const text = "Pack my box with five dozen liquor jugs. The quick brown fox jumps over the lazy dog. The five boxing wizards jump quickly.";
// Word to search for.
string target;
cin >> target;
// Capture the target and up to two words before and after.
regex const context(R"((?:([^\s]+)\s)?(?:([^\s]+)\s)?()" + target + R"()(?:\s([^\s]+))?(?:\s([^\s]+))?)");
// Perform search.
smatch matches;
regex_search(text, matches, context);
// Print results.
copy_if(matches.begin() + 1, matches.end(), ostream_iterator<string>(cout, "\n"), mem_fn(&smatch::value_type::matched));