【问题标题】:Vector searching向量搜索
【发布时间】:2020-12-20 12:30:50
【问题描述】:

基本上,我的字符串向量 vector<string> words 中有很多单词。

我需要创建一个函数,在整个向量中搜索所有带有“ly”的单词并返回它们,例如 (golly, helpfully, mostly, nearly)。

我如何使用std::find_if 函数来执行此操作,或者有其他方法可以执行此操作吗?

我还需要在我的向量中找到比7 字母长的单词,我是否仍将std::find_if 函数与>=7 一起使用?

【问题讨论】:

  • 如果您用minimal reproducible example 填写您的问题并具体指出您遇到的问题,那么回答会更容易。
  • the docs中有解释。只需将 if 与使用 std::string::find 的谓词一起使用来检查字符串是否包含所需的字符
  • 要查找超过 7 个字母的单词,您应该使用> 7,而不是>= 7

标签: c++ algorithm search stdvector stdstring


【解决方案1】:

首先,标准库中有一个更合适的算法,称为std::copy_if,而不是std::find_if(根据您的要求)。

其次,您需要根据不同的情况获得不同的单词列表。这听起来像是有一个 template function 包装了 std::copy_if 并且还提供了一种提供自定义比较(例如 lambda function)功能的方法。

因此我建议如下:

#include <algorithm> // std::copy_if
#include <iterator>  // std::cbegin, std::cend


template<typename Container, typename Predicate>
auto getElelmentsOf(const Container& container, const Predicate condition) /* noexcept */
{
    Container result;
    std::copy_if(std::cbegin(container), std::cend(container), std::back_inserter(result),
        condition);
    return result;
}

现在你可以写类似的东西

// all the words with "ly"
const auto words_with_ly = [](const auto& ele) {
    return ele.find(std::string{ "ly" }) != std::string::npos;
};
const auto elemtsOfLy = getElelmentsOf(words, words_with_ly);  // function call


// find words that are longer than 7 letters
const auto words_with_size_7_more = [](const auto& ele) { return ele.size() > 7; };
const auto elemtsOfsize7More = getElelmentsOf(words, words_with_size_7_more);  // function call

(See a Live Demo Online)

【讨论】:

    【解决方案2】:

    您可以使用std::copy_if 来获取满足某些条件的所有元素。

    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm> // for std::copy_if
    #include <iterator> // for std::back_inserter
    
    using std::vector;
    using std::string;
    
    int main(void) {
        vector<string>words={
            "golly", "hoge", "lyric", "helpfully",
            "mostly", "abcdefg", "nearly", "terrible"
        };
        vector<string> res_ly, res_7;
    
        // get all words that contains "ly"
        std::copy_if(words.begin(), words.end(), std::back_inserter(res_ly),
            [](const string& x){ return x.find("ly") != string::npos; });
    
        // get all words that are longer than 7 letters
        std::copy_if(words.begin(), words.end(), std::back_inserter(res_7),
            [](const string& x){ return x.length() > 7; });
    
        // print what we got
        std::cout << "words with \"ly\":\n";
        for (const string& s : res_ly) std::cout << "  " << s << '\n';
        std::cout << "\nwords longer than 7 letters:\n";
        for (const string& s : res_7) std::cout << "  " << s << '\n';
    
        return 0;
    }
    

    输出:

    words with "ly":
      golly
      lyric
      helpfully
      mostly
      nearly
    
    words longer than 7 letters:
      helpfully
      terrible
    

    如果你想使用std::find_if,你可以像这样重复搜索:

    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm> // for std::find_if
    #include <iterator> // for std::next
    
    using std::vector;
    using std::string;
    
    int main(void) {
        vector<string>words={
            "golly", "hoge", "lyric", "helpfully",
            "mostly", "abcdefg", "nearly", "terrible"
        };
        vector<string> res_ly;
    
        // get all words that contains "ly"
        for (vector<string>::iterator start = words.begin(); ;) {
            vector<string>::iterator next = std::find_if(start, words.end(),
                [](const string& x){ return x.find("ly") != string::npos; });
            if (next == words.end()) {
                break;
            } else {
                res_ly.push_back(*next);
                start = std::next(next, 1);
            }
        }
    
        // print what we got
        std::cout << "words with \"ly\":\n";
        for (const string& s : res_ly) std::cout << "  " << s << '\n';
    
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      我可以建议以下解决方案。

      #include <iostream>
      #include <string>
      #include <vector>
      #include <iterator>
      #include <algorithm>
      
      std::vector<std::string> copy_strings( const std::vector<std::string> &v, const std::string &s )
      {
          auto present = [&s]( const auto &item ) 
          {
              return item.find( s ) != std::string::npos; 
          };
      
          auto n = std::count_if( std::begin( v ), std::end( v ), present );
                                  
          std::vector<std::string> result;
          result.reserve( n );
          
          std::copy_if( std::begin( v ), std::end( v ), 
                        std::back_inserter( result ),
                        present );
                        
          return result;                
      }
      
      int main() 
      {
          std::vector<std::string> v =
          {
              "golly", "helpfully", "mostly", "nearly"
          };
          
          auto result = copy_strings( v, "ly" );
          
          for (const auto &item : result )
          {
              std::cout << item << ' ';
          }
          std::cout << '\n';
          
          return 0;
      }
      

      程序输出是

      golly helpfully mostly nearly
      

      【讨论】:

      • 为了result.reserve( n );,您正在对向量进行一次迭代。然后再次进行迭代以查找单词。不确定在实践中的性能如何。
      • @Const 动态重新分配内存可以占用更多类型,然后只遍历已分配的内存。
      猜你喜欢
      • 1970-01-01
      • 2020-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-28
      • 2023-03-20
      • 2014-07-19
      相关资源
      最近更新 更多