在给定要删除的值的情况下,是否有一种更聪明/更巧妙的方式来修剪矢量,类似于修剪字符串的操作,例如来自
0 0 0 1 2 3 56 0 2 4 0 0
到
1 2 3 56 0 2 4
我找不到类似修整的功能,找到/擦除是最佳选择吗?
答案 0 :(得分:8)
假设我们正在使用
std::vector<int> v;
我们要修剪零,所以
auto const is_not_zero = [](int i){ return i != 0; };
要找到第一个非零元素并删除它之前的所有内容,
auto const first_non_zero = std::find_if(v.begin(), v.end(), is_not_zero);
v.erase(b.begin(), first_non_zero);
要找到最后一个非零值,请对反向迭代器执行相同操作:
auto const last_non_zero = std::find_if(v.rbegin(), v.rend(), is_not_zero);
v.erase(last_non_zero.base(), v.end());
({std::reverse_iterator::base
从相反的一个返回基础的普通迭代器)。
答案 1 :(得分:3)
在许多情况下,最好对向量不执行任何操作,而仅对元素的相关范围使用迭代器对。您也可以使用span:
#include <gsl/span>
// ...
auto non_zeros = gsl::span(nonzeros_start_iter, nonzeros_end_iter);
,您可以像使用任何标准库容器一样使用此跨度。在C ++ 20中,您可以将gsl::span
切换为std::span
。
答案 2 :(得分:3)
这是具有给定参数的任何类型的完整实现。
template<typename T>
void TrimVector(vector<T>& vec, const T& _t)
{
auto end_index = find_if(vec.crbegin(), vec.crend(), [_t](const T& t) { return t != _t; } ).base();
vec.erase(end_index, vec.cend());
auto start_index = find_if(vec.cbegin(), vec.cend(), [_t](const T& t) { return t != _t; } );
vec.erase(vec.cbegin(), start_index);
}
要使用它,
//TrimVector<int>(MyVec, 0);
//changed as suggested below,
TrimVector(MyVec,0);
测试:
int main()
{
vector<int> myVec = { 0, 0, 0, 1, 2, 3, 56, 0, 2, 4, 0, 0 };
TrimVector(myVec, 0);
cout << "myVec:" << endl;
for (auto it = myVec.begin(); it != myVec.end(); ++it)
cout << "\t" << *it << endl;
return 0;
}