从自定义值修剪向量的最佳方法

时间:2019-05-06 12:02:01

标签: c++

在给定要删除的值的情况下,是否有一种更聪明/更巧妙的方式来修剪矢量,类似于修剪字符串的操作,例如来自

0 0 0 1 2 3 56 0 2 4 0 0

1 2 3 56 0 2 4

我找不到类似修整的功能,找到/擦除是最佳选择吗?

3 个答案:

答案 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;
}