You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为vector<string>的remove_if编写匹配指定单词的一元谓词?

How to Write a Predicate for remove_if to Remove Elements Containing a Specific Word

Let's break down the problems in your code and fix them step by step:

First: Why Your Current Code Fails

std::remove_if expects a unary predicate — a callable object that takes a single element from your vector (a std::string) and returns a bool. Right now, you're calling remove_if_found("violin") directly, which returns a bool (not a callable that can take a string). That's the immediate error.

Second, even if you fix the predicate, remove_if doesn't actually delete elements from the vector — it only moves elements you want to keep to the front, and returns an iterator pointing to the start of the "discarded" elements. You need to call erase after remove_if to shrink the vector to the correct size.


Solution 1: Use a Lambda Expression (C++11+)

This is the cleanest and most modern approach. Lambdas let you define the predicate inline, and you can capture the target word directly:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main() {
    vector<string> data { 
        "the guitar has six strings", 
        "the violin has four strings", 
        "the the violin is more difficult to learn", 
        "saxophones are a family of instruments", 
        "the drum is a set of percussions", 
        "the trumpet is a brass" 
    };
    cout << data.size() << endl; // Output: 6

    const string target_word = "violin";
    // Use a lambda to check if each string contains the target word
    auto new_end = remove_if(
        data.begin(), 
        data.end(),
        // Capture target_word by reference, check for substring existence
        [&target_word](const string& s) {
            return s.find(target_word) != string::npos;
        }
    );
    // Erase the elements that were moved to the end
    data.erase(new_end, data.end());

    cout << data.size() << endl; // Output: 4
    return 0;
}

Key Details:

  • [&target_word]: Captures the target_word variable by reference so the lambda can use it.
  • s.find(target_word) != string::npos: std::string::find returns the index of the first occurrence of the substring, or string::npos if it's not found. This condition checks if the string contains the target word.
  • data.erase(new_end, data.end()): Actually removes the unwanted elements from the vector, updating its size.

Solution 2: Use a Function Object (Functor)

If you're working with pre-C++11 code, or prefer a reusable predicate, you can define a struct with an overloaded operator():

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

struct ContainsWord {
    string target;
    // Constructor to store the target word
    ContainsWord(const string& t) : target(t) {}
    // Overload () to act as a unary predicate
    bool operator()(const string& s) const {
        return s.find(target) != string::npos;
    }
};

int main() {
    vector<string> data { 
        "the guitar has six strings", 
        "the violin has four strings", 
        "the the violin is more difficult to learn", 
        "saxophones are a family of instruments", 
        "the drum is a set of percussions", 
        "the trumpet is a brass" 
    };
    cout << data.size() << endl; // Output: 6

    auto new_end = remove_if(data.begin(), data.end(), ContainsWord("violin"));
    data.erase(new_end, data.end());

    cout << data.size() << endl; // Output: 4
    return 0;
}

Solution 3: Use std::bind (C++11+)

You can also create a binary function (taking both the string to check and the target word) and bind the target word to make it a unary predicate:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional> // Needed for std::bind and placeholders
using namespace std;
using namespace std::placeholders; // For _1 placeholder

// Binary function: checks if s contains word
bool contains_word(const string& s, const string& word) {
    return s.find(word) != string::npos;
}

int main() {
    vector<string> data { 
        "the guitar has six strings", 
        "the violin has four strings", 
        "the the violin is more difficult to learn", 
        "saxophones are a family of instruments", 
        "the drum is a set of percussions", 
        "the trumpet is a brass" 
    };
    cout << data.size() << endl; // Output: 6

    // Bind the second argument to "violin", leaving the first argument (_1) to be filled by remove_if
    auto new_end = remove_if(data.begin(), data.end(), bind(contains_word, _1, "violin"));
    data.erase(new_end, data.end());

    cout << data.size() << endl; // Output: 4
    return 0;
}

Final Notes

  • Always pair remove_if with erase: This is called the "erase-remove idiom" — it's the standard way to remove elements from a container using STL algorithms.
  • std::string::find is case-sensitive. If you need case-insensitive matching, you'd have to implement a custom check (e.g., converting both strings to lowercase before comparing).

内容的提问来源于stack exchange,提问作者Sergio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:32:40