C++ C++;-检查数组中所有值的字符串
我有一些来自Vision API的解析文本,我正在使用关键字对其进行过滤,如下所示:C++ C++;-检查数组中所有值的字符串,c++,find,C++,Find,我有一些来自Vision API的解析文本,我正在使用关键字对其进行过滤,如下所示: if (finalTextRaw.find("File") != finalTextRaw.npos) { LogMsg("Found Menubar"); } 例如,如果在字符串finalTextRaw中的任意位置找到关键字“File”,则该功能将中断,并打印日志消息 这种方法非常可靠。但我只是以这种方式做了一堆if-else-if语句,效率很低。随着
if (finalTextRaw.find("File") != finalTextRaw.npos)
{
LogMsg("Found Menubar");
}
例如,如果在字符串finalTextRaw
中的任意位置找到关键字“File”,则该功能将中断,并打印日志消息
这种方法非常可靠。但我只是以这种方式做了一堆if-else-if语句,效率很低。随着我发现更多需要过滤的单词,我宁愿效率更高一点。相反,我现在从配置文件中获取一个字符串,然后将该字符串解析为一个数组:
string filterWords = GetApp()->GetFilter();
std::replace(filterWords.begin(), filterWords.end(), ',', ' '); ///replace ',' with ' '
vector<int> array;
stringstream ss(filterWords);
int temp;
while (ss >> temp)
array.push_back(temp); ///create an array of filtered words
当然,这种语法不起作用,而且肯定比这更复杂,但希望您能理解:如果我的数组中的任何单词出现在该字符串中的任何位置,那么应该忽略该字符串,并打印一条日志消息
你知道我该如何设计这样一个函数吗?我猜这将需要某种循环。你可以使用一种基本的强力循环:
unsigned int quantity_words = array.size();
for (unsigned int i = 0; i < quantity_words; ++i)
{
std::string word = array[i];
if (finalTextRaw.find(word) != std::string::npos)
{
// word is found.
// do stuff here or call a function.
break; // stop the loop.
}
}
unsigned int quantity_words=array.size();
for(无符号整数i=0;i
上面的循环获取数组中的每个单词,并在finalTextRaw
中搜索该单词
使用一些std
算法有更好的方法。我将把这个留给其他答案
编辑1:地图和关联上面的代码让我很烦恼,因为通过
finalTextRaw
字符串的过程太多了
还有一个想法:
finalTextRaw
中的单词创建一个std::set
数组中的每个单词,检查集合中是否存在。
这减少了搜索的数量(就像搜索一棵树)
您还应该研究在
数组中创建一组单词,并找到这两组单词之间的交点。您可以使用基本的强力循环:
unsigned int quantity_words = array.size();
for (unsigned int i = 0; i < quantity_words; ++i)
{
std::string word = array[i];
if (finalTextRaw.find(word) != std::string::npos)
{
// word is found.
// do stuff here or call a function.
break; // stop the loop.
}
}
unsigned int quantity_words=array.size();
for(无符号整数i=0;i
上面的循环获取数组中的每个单词,并在finalTextRaw
中搜索该单词
使用一些std
算法有更好的方法。我将把这个留给其他答案
编辑1:地图和关联
上面的代码让我很烦恼,因为通过finalTextRaw
字符串的过程太多了
还有一个想法:
使用finalTextRaw
中的单词创建一个std::set
对于数组中的每个单词,检查集合中是否存在。
这减少了搜索的数量(就像搜索一棵树)
您还应该研究在数组中创建一组单词,并找到这两组单词之间的交点。借用Thomas的答案,ranged for循环提供了一个简洁的解决方案:
for (const auto &word : words)
{
if (finalTextRaw.find(word) != std::string::npos)
{
// word is found.
// do stuff here or call a function.
break; // stop the loop.
}
}
借用Thomas的答案,远程for循环提供了一个简洁的解决方案:
for (const auto &word : words)
{
if (finalTextRaw.find(word) != std::string::npos)
{
// word is found.
// do stuff here or call a function.
break; // stop the loop.
}
}
正如托马斯所指出的,最有效的方法是将两个文本分割成一个单词列表。然后使用std::set_intersection
查找两个列表中的匹配项。您可以使用std::vector
,只要它已排序。最终得到的是O(n*log(n))
(n=max words),而不是O(n*m)
将句子拆分为单词:
auto split(std::string_view sentence) {
auto result = std::vector<std::string>{};
auto stream = std::istringstream{sentence.data()};
std::copy(std::istream_iterator<std::string>(stream),
std::istream_iterator<std::string>(), std::back_inserter(result));
return result;
}
请注意,这在处理大量或未定义的单词时是有意义的。如果您知道这些限制,您可能希望使用更简单的解决方案(由其他答案提供)。正如Thomas所指出的,最有效的方法是将两个文本拆分为一个单词列表。然后使用std::set_intersection
查找两个列表中的匹配项。您可以使用std::vector
,只要它已排序。最终得到的是O(n*log(n))
(n=max words),而不是O(n*m)
将句子拆分为单词:
auto split(std::string_view sentence) {
auto result = std::vector<std::string>{};
auto stream = std::istringstream{sentence.data()};
std::copy(std::istream_iterator<std::string>(stream),
std::istream_iterator<std::string>(), std::back_inserter(result));
return result;
}
请注意,这在处理大量或未定义的单词时是有意义的。如果您知道限制,您可能希望使用更简单的解决方案(由其他答案提供)。啊,似乎我遇到了错误C2440“初始化”:无法从“\u Ty”转换为“std::basic\u string”
。我认为在这种情况下,这意味着我的数组实际上没有被定义?我想我不能确定我的第一段代码首先是否正确生成了数组。@肖邦我们需要查看您的实际代码才能回答这个问题。啊,似乎我遇到了错误C2440“初始化”:无法从“\Ty”转换为“std::basic\u string”
。我认为在这种情况下,这意味着我的数组实际上没有被定义?我想我不能确定我的第一段代码首先是否正确生成了数组。@肖邦我们需要查看您的实际代码才能回答这个问题。您知道过滤器中的字数吗?在原始文本中?检查你知道过滤器中的字数吗?在原始文本中?检查