我有一个std::vector<int>,我想删除第n个元素。我怎么做呢?

std::vector<int> vec;

vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);

vec.erase(???);

要删除单个元素,你可以这样做:

std::vector<int> vec;

vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);

// Deletes the second element (vec[1])
vec.erase(std::next(vec.begin()));

或者,一次删除多个元素:

// Deletes the second through third elements (vec[1], vec[2])
vec.erase(std::next(vec.begin(), 1), std::next(vec.begin(), 3));

std::vector上的erase方法重载了,所以调用它可能更清楚

vec.erase(vec.begin() + index);

当你只想擦除一个元素时。


template <typename T>
void remove(std::vector<T>& vec, size_t pos)
{
    std::vector<T>::iterator it = vec.begin();
    std::advance(it, pos);
    vec.erase(it);
}

erase方法将以两种方式使用:

擦除单个元素: 向量。Erase (vector.begin() + 3);//删除第四个元素 元素擦除范围: 向量。删除(vector.begin() + 3, vector.begin() + 5);//从第4个元素删除到第6个元素


如果你使用较大的向量(大小为> 100,000),并且想要删除大量的元素,我建议这样做:

int main(int argc, char** argv) {

    vector <int> vec;
    vector <int> vec2;

    for (int i = 0; i < 20000000; i++){
        vec.push_back(i);}

    for (int i = 0; i < vec.size(); i++)
    {
        if(vec.at(i) %3 != 0)
            vec2.push_back(i);
    }

    vec = vec2;
    cout << vec.size() << endl;
}

该代码获取vec中不能被3整除的所有数字,并将其复制到vec2。然后在vec中复制vec2。它非常快。要处理200,000,000个元素,这个算法只需要0.8秒!

我用擦除方法做了同样的事情,这需要很多很多时间:

Erase-Version (10k elements)  : 0.04 sec
Erase-Version (100k elements) : 0.6  sec
Erase-Version (1000k elements): 56   sec
Erase-Version (10000k elements): ...still calculating (>30 min)

实际上,擦除功能适用于两种配置文件:

删除单个元素 迭代器擦除(迭代器位置); 删除一系列元素 迭代器擦除(迭代器先,迭代器后);

因为std:: vvector .begin()标志着容器的开始,如果我们想删除vector中的第i个元素,我们可以使用:

vec.erase(vec.begin() + index);

如果你仔细观察,vecc .begin()只是一个指向我们的向量的起始位置的指针,并且向它添加i的值将增加指向i位置的指针,因此我们可以通过以下方式访问指向第i个元素的指针:

&vec[i]

所以我们可以这样写:

vec.erase(&vec[i]); // To delete the ith element

删除一个元素的方法如下:

// declaring and assigning array1 
std:vector<int> array1 {0,2,3,4};

// erasing the value in the array
array1.erase(array1.begin()+n);

欲了解更广泛的概况,请访问:http://www.cplusplus.com/reference/vector/vector/erase/


前面的答案假设您总是有一个带符号的索引。遗憾的是,std::vector使用size_type进行索引,使用difference_type进行迭代器算术,所以如果你启用了"-Wconversion"和friends,它们就不能一起工作。这是另一种回答问题的方式,同时能够处理有符号和无符号:

删除:

template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
void remove(std::vector<T> &v, I index)
{
    const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);
    v.erase(iter);
}

采取:

template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
T take(std::vector<T> &v, I index)
{
    const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);

    auto val = *iter;
    v.erase(iter);

    return val;
}

如果你有一个无序向量,你可以利用它是无序的这一事实,并使用我在CPPCON上从Dan Higgins那里看到的东西

template< typename TContainer >
static bool EraseFromUnorderedByIndex( TContainer& inContainer, size_t inIndex )
{
    if ( inIndex < inContainer.size() )
    {
        if ( inIndex != inContainer.size() - 1 )
            inContainer[inIndex] = inContainer.back();
        inContainer.pop_back();
        return true;
    }
    return false;
}

由于列表顺序无关紧要,只需取列表中的最后一个元素并将其复制到您想要删除的项之上,然后弹出并删除最后一项。


这里还有一种方法,如果你想删除一个元素,通过在vector中找到它的值,你只需要在vector上做这个。

vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));

它会把你的价值从这里抹去。 谢谢


最快的方法(对于时间复杂度()=常量的编程竞赛)

可在1秒内擦除100M项目;

    vector<int> it = (vector<int>::iterator) &vec[pos];
    vec.erase(it);

最易读的方式: Vec.erase (vec.begin() + pos);


我建议阅读这篇文章,因为我相信这就是你在寻找的东西。https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom

举个例子

 vec.erase(vec.begin() + 1, vec.begin() + 3);

你将擦除向量的第n个元素,但当你擦除第二个元素时,向量的所有其他元素将被移动,向量的大小将为-1。如果循环遍历vector,这可能是个问题,因为vector size()正在减小。如果你有这样的问题,建议使用标准c++库中现有的算法。和"remove"或"remove_if"。

希望这对大家有所帮助


对于一些人来说,这似乎是显而易见的,但要详细说明以上的答案:

如果你在整个向量上使用erase循环删除std::vector元素,你应该以相反的顺序处理你的向量,也就是说使用

For (int I = v.size() - 1;I >= 0;我——)

而不是(古典的)

For (int I = 0;I < v.size();我+ +)

原因是索引会受到erase的影响,所以如果你删除了第4个元素,那么之前的第5个元素就变成了新的第4个元素,如果你在执行i++,它就不会被循环处理。

下面是一个简单的例子来说明这一点,我想删除一个int向量的所有odds元素;

#include <iostream>
#include <vector>

using namespace std;

void printVector(const vector<int> &v)
{
    for (size_t i = 0; i < v.size(); i++)
    {
        cout << v[i] << " ";
    }
    cout << endl;
}

int main()
{    
    vector<int> v1, v2;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
        v2.push_back(i);
    }

    // print v1
    cout << "v1: " << endl;
    printVector(v1);
    
    cout << endl;
    
    // print v2
    cout << "v2: " << endl;
    printVector(v2);
    
    // Erase all odd elements
    cout << "--- Erase odd elements ---" << endl;
    
    // loop with decreasing indices
    cout << "Process v2 with decreasing indices: " << endl;
    for (int i = v2.size() - 1; i >= 0; i--)
    {
        if (v2[i] % 2 != 0)
        {
            cout << "# ";
            v2.erase(v2.begin() + i);
        }
        else
        {
            cout << v2[i] << " ";
        }
    }
    cout << endl;
    cout << endl;
    
    // loop with increasing indices
    cout << "Process v1 with increasing indices: " << endl;
    for (int i = 0; i < v1.size(); i++)
    {
        if (v1[i] % 2 != 0)
        {
            cout << "# ";
            v1.erase(v1.begin() + i);
        }
        else
        {
            cout << v1[i] << " ";
        }
    }
    
    
    return 0;
}

输出:

v1:
0 1 2 3 4 5 6 7 8 9

v2:
0 1 2 3 4 5 6 7 8 9
--- Erase odd elements ---
Process v2 with decreasing indices:
# 8 # 6 # 4 # 2 # 0

Process v1 with increasing indices:
0 # # # # #

注意,在第二个增加索引的版本中,偶数不会显示出来,因为i++跳过了它们

还要注意的是,以相反的顺序处理向量,你不能对索引使用unsigned类型(for (uint8_t i = v.size() -1;... 不会工作)。这是因为当i = 0时,i—将溢出,并等于255 uint8_t为例(因此循环不会停止,因为i仍然是>= 0,可能超出了向量的边界)。


删除带索引的元素:

vec.erase(vec.begin() + index);

删除带值的元素:

vec.erase(find(vec.begin(),vec.end(),value));

如果需要擦除for循环中的元素,请执行以下操作:

for(int i = 0; i < vec.size(); i++){

    if(condition)
        vec.erase(vec.begin() + i);

}

你需要使用标准模板库的std::vector::erase函数。

示例:从vector中删除一个元素(使用index)

// Deleting the eleventh element from vector vec
vec.erase( vec.begin() + 10 ); 

以上代码的解释

std::向量< T,分配器>::消除用法:

iterator erase (iterator position); // until C++11
iterator erase( const_iterator pos ); // since C++11 and until C++20
constexpr iterator erase( const_iterator pos ); // since C++20

这里有一个参数position,它是指向要从vector中移除的单个元素的迭代器。 成员类型iterator和const_iterator是指向元素的随机访问迭代器类型。

它是如何工作的

擦除函数做以下工作:

它从向量中删除单个元素(position)或一组元素([first, last))。 它通过删除被销毁的元素的数量来减小容器的大小。

注意:迭代器pos必须有效且可解引用。因此end()迭代器(有效,但不可解引用)不能用作pos的值。

返回值和复杂度

返回值是一个迭代器,指向被函数调用擦除的最后一个元素后面的元素的新位置。这是擦除序列中最后一个元素的操作的容器结束。

成员类型迭代器是指向元素的随机访问迭代器类型。

在这里,时间复杂度与删除的元素数量(销毁)加上最后一个元素删除后的元素数量(移动)成线性关系。