2009-05-17 506 views
344

我有一个std :: vector < int>,我想删除第n个元素。我怎么做?如何从索引中删除std :: vector <>中的元素?

std::vector<int> vec; 

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

vec.erase(???); 
+4

考虑使用一个std :: deque,它提供两端的插入和删除。 – Dario 2009-05-17 18:20:27

+11

不,不要考虑使用deque只是因为你可能想删除一个元素,这真的是一个糟糕的建议。有很多原因可能会导致你想要使用deque或vector。确实,从矢量中删除一个元素可能会很昂贵 - 尤其是如果矢量很大,但没有理由认为一个deque会比刚刚发布的代码示例的矢量更好。 – Owl 2017-04-01 21:10:27

+2

例如,如果您有一个图形应用程序,您可以在其中显示交互式地插入/移除事物的“列表”,请考虑每秒通过列表50到100次来显示它们,并且您可以添加/每分钟几次。因此,将“列表”作为一个向量来实现,在总体效率方面可能是更好的选择。 – 2017-05-28 17:54:22

回答

460

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

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); 
+15

注意二元运算符+`是__not__必须为其他容器类型的迭代器定义,如`list :: iterator`(你不能在`std :: list`上执行`list.begin()+ 2`,使用[`std :: advance`](http://www.cplusplus.com/reference/iterator/advance/)) – bobobobo 2013-03-14 23:35:02

+0

你是说“+1”是第一个元素myVector [0]或它的实际位置myVector [1] – 2014-09-19 07:38:00

159

性病擦除方式::矢量超载,所以可能更清楚地致电

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

当你只想擦除一个元素。

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

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

  1. 删除单个元件:元件

    vector.erase(vector.begin() + 3); // Deleting the third element 
    
  2. 擦除范围:

    vector.erase(vector.begin() + 3, vector.begin() + 5); // Deleting from third element to fifth element 
    
1

如果你有大载体(大小> 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) 
3

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

  • 删除单个元素

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

    iterator erase (iterator first, iterator last); 
    

因为的std :: vec.begin()标记容器的开始,如果我们想删除我们的矢量的第i个元素,我们可以使用:

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

如果您仔细观察,vec。开始()仅仅是一个指向我们的矢量的起始位置,加上我的价值,它递增指针到我的位置,所以我们可以将通过访问指向第i个元素:

&vec[i] 

所以我们可以这样写:

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

以前的答案假设你总是有一个签名索引。不幸的是,std::vector使用size_type进行索引,而difference_type用于迭代器算术,所以如果您启用了“-Wconversion”和朋友,它们不会一起工作。这是另一种方式来回答这个问题,同时能够处理符号和无符号:

要删除:

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

如果你有一个无序矢量可以利用事实,它是无序的,并使用我从丹希金斯在CPPCON看到的东西

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

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

相关问题