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

如何为vector<string>实现remove_if_not功能?

问题描述

我想实现类似下面代码的功能:

v.erase(remove_if(v.begin(), v.end(), !pointer_to_func), v.end());

其中v是std::vector<std::string>类型,pointer_to_func是如下函数指针:

bool (*pointer_to_func)(std::string);

我知道!pointer_to_func写法错误,但这是我想要的核心逻辑——保留满足pointer_to_func条件的元素,移除不满足的。

该功能在类中的声明如下:

void Place::filter_ss(bool (*n)(std::string)){}; // 函数指针标注为FP

我试过多种方法,但not1、not2、ptr_fun这些方法已经被废弃/移除了。函数在main中的调用方式如下:

int main(){
    // 所有元素push_back到vector v中
    Place p{"Observatory", "Airport", "Delicatessen", "Theater", "Vacation"}; 
    // 这个函数是难点,它接收字符串直接删除不包含指定子串的单词
    p.filter_ss(at); 
    // 循环应该输出: Observatory Delicatessen Theater Vacation
    for (size_t x = 0; x < p.v.size(); x++) 
        cout << p.v[x] << " ";
    ... // 其他操作
    ... // 更多操作
    return 0;
}

注:原代码中Place p(){"..."}是语法错误,修正为Place p{"..."};循环条件的逗号需改为分号,cout需输出p.v[x]而非v[x]。

我的代码只有用预定义测试函数时能正常工作,比如:

bool st(string str){
    return str.find("st") < string::npos;
}

我尝试了几种实现方式,但都达不到预期效果,求正确实现方案或方向指导。


尝试的实现思路

  1. 临时容器拷贝法
void Place::filter_ss(bool (*n)(string)){
    pointer_to_func = n;
    vector<string> temp;
    for(size_t t = 0; t < v.size(); t++){
        if(pointer_to_func(v[t])){
            temp.push_back(v[t]);
        }
    }
    v.clear();
    for(auto s : temp)
        v.push_back(s);
}
  1. 结合erase-remove_if和废弃的not1/ptr_fun
void Place::filter_ss(bool (*n)(string)){
    pointer_to_func = n;
    v.erase(remove_if(v.begin(), v.end(), not1(ptr_fun(pointer_to_func))), v.end());
}
  1. copy_if用法(逻辑错误)
void Place::filter_ss(bool (*n)(string)){
    vector<string> temp;
    pointer_to_func = n;
    copy_if(temp.begin(), temp.end(), back_inserter(v), pointer_to_func);
}

正确实现方案

由于C11及以后not1/ptr_fun已被废弃,推荐使用lambda表达式反转判断逻辑,这是最简洁且符合现代C规范的方式。

方案1:lambda配合erase-remove_if(最优)

void Place::filter_ss(bool (*pred)(std::string)) {
    // 用lambda反转判断条件:移除不满足原条件的元素
    v.erase(
        std::remove_if(v.begin(), v.end(),
            [pred](const std::string& s) { return !pred(s); }
        ),
        v.end()
    );
}

remove_if会移除所有返回true的元素,lambda返回!pred(s),刚好把不满足原条件的元素标记为待移除,最终通过erase完成删除。无需额外容器,效率最高。

方案2:修复临时容器拷贝法(兼容旧标准)

如果环境不支持C++11,可优化第一种尝试的代码:

void Place::filter_ss(bool (*pred)(std::string)) {
    std::vector<std::string> temp;
    temp.reserve(v.size()); // 预分配空间提升效率
    for (const auto& s : v) { // 范围for循环更简洁
        if (pred(s)) {
            temp.push_back(s);
        }
    }
    v.swap(temp); // 用swap代替clear+push_back,避免内存重新分配
}

方案3:修正copy_if逻辑

第三种尝试的源容器和目标容器搞反了,正确写法如下:

void Place::filter_ss(bool (*pred)(std::string)) {
    std::vector<std::string> temp;
    temp.reserve(v.size());
    std::copy_if(v.begin(), v.end(), std::back_inserter(temp), pred);
    v.swap(temp);
}

copy_if会把原容器v中满足条件的元素拷贝到temp,最后用swap替换原容器。


之前代码失败的原因

  • 尝试2使用了已废弃的not1/ptr_fun,C++17中已完全移除,编译器会报错;
  • 尝试3中copy_if的源容器是空的temp,目标是原容器v,逻辑完全错误;
  • main中的代码存在语法错误,导致对象初始化或输出逻辑异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 15:20:30