如何从std :: vector<>中删除元素?按指数?

时间:2009-05-17 17:59:36

标签: c++ stl vector erase

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

std::vector<int> vec;

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

vec.erase(???);

16 个答案:

答案 0 :(得分:596)

要删除单个元素,您可以执行以下操作:

std::vector<int> vec;

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

// Deletes the second element (vec[1])
vec.erase(vec.begin() + 1);

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

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

答案 1 :(得分:188)

std :: vector上的erase方法过载,因此调用

可能更清晰
vec.erase(vec.begin() + index);

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

答案 2 :(得分:49)

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);
}

答案 3 :(得分:14)

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

  1. 删除单个元素:

    vector.erase( vector.begin() + 3 ); // Deleting the fourth element
    
  2. 删除元素范围:

    vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
    

答案 4 :(得分:6)

实际上,erase功能适用于两个配置文件:

  • 删除单个元素

    iterator erase (iterator position);
    
  • 删除一系列元素

    iterator erase (iterator first, iterator last);
    

由于std :: vec.begin()标记了容器的开头,如果我们要删除vector中的第i个元素,我们可以使用:

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

如果你仔细观察,vec.begin()只是指向我们向量的起始位置的指针,并且将i的值添加到它会增加指向i位置的指针,所以我们可以访问指向第i个元素的指针由:

&vec[i]

所以我们可以写:

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

答案 5 :(得分:6)

如果你有一个无序的向量,你可以利用它无序的事实,并使用我在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;
}

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

答案 6 :(得分:6)

使用索引擦除元素:

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

使用值擦除元素:

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

答案 7 :(得分:4)

如果您使用大型矢量(大小> 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。它很快。要处理20,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)

答案 8 :(得分:2)

要删除元素,请使用以下方法:

render: function() {
  return (
    <form ref="formToSubmit" onSubmit={this.handleSubmit}>
       <input name='myInput'/>
       <input onClick={this.submitForm} type="submit" value="Validate" />
    </form>
  );
}

对于更广泛的概述,您可以访问:http://www.cplusplus.com/reference/vector/vector/erase/

答案 9 :(得分:0)

之前的答案假设您始终拥有签名索引。遗憾的是,std::vector使用size_type进行索引,difference_type用于迭代算术,因此如果你有&#34; -Wconversion&#34;它们就不能一起工作。和朋友启用。这是回答问题的另一种方法,同时能够处理签名和未签名:

删除:

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

答案 10 :(得分:0)

如果要通过在vector中找到元素的值来删除元素,这是另一种方法,只需在vector上进行操作即可。

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

它将从此处删除您的值。 谢谢

答案 11 :(得分:0)

最快的方式(用于通过时间复杂度()=常数进行编程竞赛)

可以在1秒钟内擦除1亿个项目;

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

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

答案 12 :(得分:0)

怎么样?

void squeeze(vector<int> &v)
{
    int j = 0;
    for (int i = 1; i < v.size(); i++)
        if (v[i] != v[j] && ++j != i)
            v[j] = v[i];
    v.resize(j + 1);
}

答案 13 :(得分:0)

我建议您阅读这篇文章,因为我相信您正在寻找的内容。https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom

如果您使用

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

您将擦除向量的第n个元素,但是当擦除第二个元素时,向量的所有其他元素将被移动并且向量大小将为-1。如果由于矢量size()减小而遍历矢量,则可能会出现问题。如果您有这样的问题,则提供的链接建议使用标准C ++库中的现有算法。和“删除”或“删除_if”。

希望这对您有帮助

答案 14 :(得分:0)

对于某些人来说似乎很明显,但需要详细说明以上答案:

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

for (int i = v.size() - 1; i >= 0; i--)

代替(经典)

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

原因是索引受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++而被跳过的偶数也不会显示

答案 15 :(得分:-1)

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

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

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

}