C++ 使用copy_if获得数组vector掩膜

本文详细介绍如何使用C++标准模板库中的copy_if算法,从一个数组中筛选出指定条件的元素并复制到另一个数组。通过示例代码,展示了如何结合lambda表达式和掩膜数组实现高效的数据筛选。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设给定一个数组vector<double> veca以及对应的掩膜(即指示标志数组)vector<bool> flags,获得veca中对应flags中为true的元素。

假设veca{0.1, 0.2, 0.3, 0.4}flags{true, false, false, true},则vecb应该为{0.1, 0.4}

使用for循环自然可以很简单地解决这个问题,但是想要用标准模板库中的算法实现需要使用copy_if。使用copy算法的复制拷贝效率要比for的效率要高一些。

copy_if的由四个参数,前两个是输入元素的迭代器,拷贝两个迭代器之间的元素,第三个将元素拷贝到的位置,第四个是选择条件,即只拷贝改条件返回true的元素。

#include <vector>
#include <algorithm>
#include <iostream>
#include <numeric>    // accumulate
#include <iterator>

int main()
{
    std::vector<bool> flags{ true, true, false, true};
    std::vector<double> veca{ 0.1, 0.2, 0.3, -0.1 };
    
    std::vector<double> vecb;
    vecb.reserve(std::accumulate(flags.begin(), flags.end(), 0));
    
    // vecb在reserve之后并没有未元素分配内存,插入应该使用back_inserter(vecb)
    // vecb在resize之后为元素分配了内存,使用back_inserter(vecb)会在已经分配内存的元素之后插入
    // 这时应该使用 vecb.begin(),对已经分配的内存进行覆盖
    size_t i = 0;
    std::copy_if(veca.begin(), veca.end(), std::back_inserter(vecb),
                [&i, &flags](double a){return flags[i++]; });
    
    for (auto &s : vecb)
        std::cout << s << std::endl;

//  i = 0;
//  std::vector<double> vecc;
//  std::remove_copy_if(veca.begin(), veca.end(), std::back_inserter(vecc),
//      [&i, &flags](double a){return flags[i++]; });
//  std::cout << "veca\n";
//  for (auto& s : veca)
//      std::cout << s << "\t";
//  std::cout << "\nvecc\n";
//  for (auto& s : vecc)
//      std::cout << s << "\t";
    return 0;
}

使用lambda表达式作为第四个元素,捕获掩膜数组flags和元素序号i
注意lambda表达式中flagsi都是使用的引用捕获,对于数组等数据结构要使用引用捕获,而且我们希望在lambda表达式中改变i的值,因此i也要是用引用捕获。
关于C++ lambda表达式更加详细的说明可参考博客博客

要注意的是reserveresize的不同。

  • reserve只调整数组的capacity,并不分配元素分配内存,因此需要则copy_if的第三个参数使用back_insterter
  • resize为元素分配好了空间,如果在copy_if的第三个参数使用back_inserter,则会在已经分配内存的元素后面插入,正确地做法是使用vecb.begin(),对已经分配内存的元素进行覆盖。

remove_copy_if感觉和copy_if差不多,就是逻辑相反,使用remove_copy_if会在第三个参数的位置上收集到第四个参数返回false的元素。具体差别还要在继续查查资料。

转载于:https://www.cnblogs.com/zi-wang/p/9961604.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值