2009-05-17 542 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; 
} 

由於列表順序無關緊要,只需將列表中的最後一個元素複製到要移除的項目的頂部,然後彈出並刪除最後一項。

相關問題