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


    假设给定一个数组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
    ";
    // 	for (auto& s : veca)
    // 		std::cout << s << "	";
    // 	std::cout << "
    vecc
    ";
    // 	for (auto& s : vecc)
    // 		std::cout << s << "	";
    	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的元素。具体差别还要在继续查查资料。

  • 相关阅读:
    02.简单的DOM操作
    03.获取和设置元素特性的值
    异常为"当IDENTITY_INSERT设置为OFF时" 的解决
    GridView的RowCommand事件中取得行索引 技巧
    01.判断页面加载完成的方法
    今天新开了博客园
    C#巧用anchor和dock设计复杂界面(控件随着窗体大小的变化而变化)
    C#如何使用webbrowser控件制作一个简易的IE浏览器(菜鸟级)
    断箭——不相信自己的意志,永远也做不成将军
    成长与成功
  • 原文地址:https://www.cnblogs.com/zi-wang/p/9961604.html
Copyright © 2020-2023  润新知