c++--remove()函数

本文详细介绍了C++中四个移除元素的函数:remove()用于移除指定元素,remove_copy()用于复制元素到新容器并移除原位置的元素,remove_if()和remove_copy_if()则带有谓词,根据条件移除或复制元素。同时,std::back_inserter作为输出迭代器适配器,用于在容器尾部插入元素。
摘要由CSDN通过智能技术生成


C++ remove、remove_copy、remove_if和remove_copy_if函数使用详解

如果不知道具体的场景,即元素保存在什么样的容器中,是不能从序列中移除元素的。因此,“移除元素的”算法也无法做到这一点,它们只会重写被选择的元素或者忽略复制的元素。移除操作不会改变被“移除”元素的序列的元素个数。
有 4 种移除算法:

  • remove() :可以从它的前两个正向迭代器参数指定的序列中移除和第三个参数相等的对象。基本上每个元素都是通过用它后面的元素覆盖它来实现移除的。它会返回一个指向新的最后一个元素之后的位置的迭代器。
  • remove_copy() :可以将前两个正向迭代器参数指定的序列中的元素复制到第三个参数指定的目的序列中,并忽略和第 4 个参数相等的元素。它返回一个指向最后一个被复制到目的序列的元素的后一个位置的迭代器。序列不能是重叠的。
  • remove_if() :可以从前两个正向迭代器指定的序列中移除能够使作为第三个参数的谓词返回 true 的元素。
  • remove_copy_if() :可以将前两个正向迭代器参数指定的序列中,能够使作为第 4 个参数的谓词返回 true 的元素,复制到第三个参数指定的目的序列中。它返回一个指向最后一个被复制到目的序列的元素的后一个位置的迭代器。序列不能是重叠的。

1. remove()

可以按如下方式使用 remove():

std::vector<double>samples {1.5, 2.6, 0, 3.1, 0, 0, 4.1, 0, 6.7, 0};
samples.erase(std::remove(samples.begin(), samples.end(), 0), samples.end());
for (const auto &it : samples) {
    std::cout << it << " ";
}
std::cout << std::endl;
// 1.5 2.6 3.1 4.1 6.7

在这里插入图片描述

sample 中不应包含为 0 的值。remove() 算法会通过左移其他元素来覆盖它们,通过这种方式就可以消除杂乱分布的 0。remove() 返回的迭代器指向通过这个操作得到的新序列的尾部,所以可以用它作为被删除序列的开始迭代器来调用 samples 的成员函数 erase()。

2. remove_copy()

如果想保留原始序列,并生成一个移除选定元素之后的副本,可以使用 remove_copy()。 例如:

std::vector<double> samples {1.5, 2.6, 0, 3.1, 0, 0, 4.1, 0, 6.7, 0}; 
std::vector<double> edited_samples;
std::remove_copy(samples.begin(), samples.end(), std::back_inserter(edited_samples), 0);

在这里插入图片描述

samples 容器中的非零元素会被复制到 edited_samples 容器中,edited_samples 正好是一个 vector 容器。通过 back_insert_iterator 对象将这些元素添加到 edited_samples,因此这个容器只包含从 sample 中复制的元素。

3. remove_if()

remove_if() 提供了更强大的能力,它能够从序列中移除和给定值匹配的元素。谓词会决定一个元素是否被移除;它接受序列中的一个元素为参数,并返回一个布尔值。例如:

using Name = std::pair<std::string, std::string>; // First and second name
std::vector<Name> blacklist { {"Al", "Bedo"},  {"Ann", "Ounce"},  {"Jo","King"}};
std::vector<Name> candidates {{"Stan", "Down"},  {"Al", "Bedo"},  {"Dan", "Druff"}, 
                            {"Di", "Gress"},  {"Ann", "Ounce"},  {"Bea", "Gone"}}; 
candidates.erase(std::remove_if(candidates.begin(), candidates.end(), [&blacklist](const Name& name) { 
    return std::count(blacklist.begin(), blacklist.end(), name); 
    // blacklist.count(name); 该写法不正确
}), std::end(candidates)); 

for (const auto &name : candidates) {
    std::cout << '"' << name.first << " " << name.second << "\" ";
}
std::cout << std::endl;  // "Stan Down" "Dan Druff" "Di Gress" "Bea Gone"

在这里插入图片描述

这段代码用来模拟候选人申请成为倶乐部会员。那些众所周知的不安分人士的姓名被保存在 blacklist 中,它是一个集合。当前申请成为会员的候选人被保存在 candidates 容器中,它是一个 vector容器。用 remove_if() 算法来保证不会有 blacklist 中的姓名通过甄选过程。这里的谓词是一个以引用的方式捕获 blacklist 容器的 lambda 表达式。谓词返回的值会被隐式转换为布尔值,因此对于每一个出现在 blacklist 中的候选人,谓词都会返回 true,然后会将它们从 candidates 中移除。

4. remove_copy_if()

remove_copy_if() 之于 remove_copy(),就像 remove_if() 之于 remove。下面展示它是如何工作的:

std::vector<Name> blacklist { {"Al", "Bedo"},  {"Ann", "Ounce"},  {"Jo", ,"King" } };
std::vector<Name> candidates { {"Stan", "Down"}, { "Al", "Bedo"}, {"Dan", "Druff"}, 
                             {"Di", "Gress"}, {"Ann", "Ounce"}, {"Bea", "Gone"}};
std::vector<Name> validated;
std::remove_copy_if(candidates.begin(), candidates.end(), std::back_inserter(validated), [&blacklist] (const Name& name) { 
    return std::count(blacklist.begin(), blacklist.end(), name); 
});

这段代码实现了和前一段代码同样的功能,除了结果被保存在 validated 容器中和没有修改 candidates 容器之外。

5. std::back_inserter()

std::back_inserter 是一个输出迭代器适配器,用于将元素插入到容器的尾部。它可以用于算法和函数需要支持插入操作的情况。下面是一个使用 std::back_inserter 的示例:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

int main() {
    std::vector<int> source = {1, 2, 3, 4, 5};
    std::vector<int> destination;

    // 使用 std::back_inserter 将元素插入到 destination 容器的尾部
    std::copy(source.begin(), source.end(), std::back_inserter(destination));

    // 输出 destination 容器的元素
    for (const auto& item : destination) {
        std::cout << item << " ";
    }
    std::cout << std::endl;

    return 0;
}

在上述示例中,有一个名为 source 的整数向量,其中包含了一些初始数据。将 source 的所有元素复制到另一个名为 destination 的向量中,使用 std::back_inserter 可以很方便地实现。
在 std::copy 算法中,传入 std::back_inserter(destination) 作为输出迭代器。std::copy 算法会遍历 source 向量的元素,并将每个元素插入到 destination 容器的尾部,由 std::back_inserter 负责自动调整容器的大小并执行插入操作。
最后,使用循环遍历输出 destination 容器中的元素,以验证插入是否成功。运行结果将是 1 2 3 4 5,说明 std::back_inserter 正确地将元素插入到了 destination 容器的尾部。

宁可枝头抱香死,何曾吹落北风中。
2024年3月21日20:58:57

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值