【问题标题】:What is the best way to convert a std::find_if on a vector to a loop?将向量上的 std::find_if 转换为循环的最佳方法是什么?
【发布时间】:2015-10-20 00:40:37
【问题描述】:

所以我有以下 lambda 函数来搜索字符串向量中的某个子字符串。

喜欢一些随机字符串"water" "attic" "cat" "pool"

我想返回所有包含"at" 的字符串 .

auto iter = std::find_if(myVector.begin(),
                         myVector.end(),
                         [subSequence](std::string s) -> bool { return (subSequence == s); });
if ( iter != myVector.end() ){
    std::cout << *iter << "\n";     
}

我的问题是,将其扩展到循环遍历我的整个向量的最佳方法是什么?我是新手,我尝试过的一切都不起作用。这是否可行,还是我需要考虑另一种方法?

【问题讨论】:

  • std::find_if 只能用于容器的一个元素是什么意思find_if 正在遍历整个 vector,但您在 lambda 中没有做任何有意义的事情。你可能想要[&amp;subSequence](std::string const&amp; s) { return s == subSequence; } 之类的东西。
  • 您的代码没有意义,subSequence == subSequence 将始终返回 true。根据您搜索容器的频率,您可能需要考虑使用unordered_setunordered_multset
  • 我猜您正在寻找方法来返回满足您的条件的序列的多个元素。你可能想看看lower_bound,upper_bound,equal_range,这里解释了stackoverflow.com/questions/23554509/…

标签: c++ loops c++11 vector stl


【解决方案1】:

试试这个:(更新以匹配更新的问题)

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::vector<std::string> myVector = {"cat","bye","what's up?"};
    std::string subString = "at";

    //Create a lambda function to check if a string contains subString
    //Uses s.find(subString), which returns the position of subString in s,
    //  and checks that it doesn't equal the end of the string 
    auto containsSubString = [subString](std::string s){
        return s.find(subString) != std::string::npos;};

    auto iter = std::find_if(myVector.begin(),
                             myVector.end(),
                             containsSubString);

    //Use a while loop, checking whether iter is at the end of myVector
    //Do a find_if starting at the item after iter, std::next(iter)
    while (iter != myVector.end())
    {
        std::cout << *iter << std::endl;
        iter = std::find_if(std::next(iter),
                            myVector.end(),
                            containsSubString);
    }

    return 0;
}

预期输出


怎么了?

您的代码存在问题

  1. 您的 lambda 只是将 subSequencesubSequence 进行了比较,因此它始终返回 true。
  2. 您正确使用了std::find_if,但诀窍是将其插入while 循环中,以检查您是否已经到达向量的末尾。
  3. 虽然在 lambda 中包含 -&gt; bool 并没有什么坏处,但这并不是绝对必要的,因为编译器可以从 lambda 的定义中推断出该信息(s.find(subString) != std::string::npos 将始终返回一个布尔值)。只有在编译器可能不明确时(或者如果您想让其他可能阅读您的代码的程序员更清楚),您才需要明确提及类型。

编辑:正如@Yakk 的回答中所见,实际上使用std::next(iter) 而不是iter + 1 更好,就像我最初使用的那样。
这是因为std::next(iter) 将适用于所有类型的 C++ STL 容器,而仅递增迭代器并不适用于所有容器(尽管它适用于最常见的容器,例如 std::arraystd::vector)。

【讨论】:

  • 谢谢。你的回答让我意识到我没有做我想的那样。我正在搜索字符串中的子字符串。我更新了我的问题以反映这一点。
  • 好的,是的,那么您需要进一步观察。您是否需要在包含子字符串的向量中查找所有字符串?在这种情况下,找出如何查找字符串是否有子字符串,然后将其放入 lambda 中。我实际上不记得如何检查一个字符串是否包含我头顶的子字符串,但我会推荐一个好的搜索引擎。 :) 祝你好运!
  • @user5447431 我已经更新了我的答案以匹配您的新问题(尽管也许您应该提出一个新问题——我不确定 StackOverflow 社区对此有何看法)。无论如何,我希望这会有所帮助!
  • 谢谢!这正是我想要做的。
  • 太棒了!如果它对您有用,请随时接受它! ;)
【解决方案2】:

[subSequence](std::string) -&gt; bool { return (subSequence == subSequence); } 替换为[&amp;](std::string const&amp;str) -&gt; bool { return (subSequence == str); } 并在早上给我打电话。

如果您想要下一个元素,但它没有返回 .end(),只需将 begin 子句替换为 std::next(it),它是最后一个返回的元素。要么循环,要么递归。

【讨论】:

    猜你喜欢
    • 2014-02-18
    • 1970-01-01
    • 2022-12-20
    • 2016-05-29
    • 2012-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多