2016-08-18 51 views
4

假設我有std::vector<std::pair<int,Direction>>使用erase-remove_if用法

我想使用erase-remove_if成語從矢量中刪除對。

stopPoints.erase(std::remove_if(stopPoints.begin(), 
           stopPoints.end(), 
           [&](const stopPointPair stopPoint)-> bool { return stopPoint.first == 4; })); 

我想刪除已。首先值設置爲4

在我的例子我對所有對:

- 4, Up 
- 4, Down 
- 2, Up 
- 6, Up 

然而,當我執行擦除的remove_if,我剩下:

- 2, Up 
- 6, Up 
- 6, Up 

我在做什麼錯在這裏?

回答

9

正確的代碼:

stopPoints.erase(std::remove_if(stopPoints.begin(), 
           stopPoints.end(), 
           [&](const stopPointPair stopPoint)-> bool 
             { return stopPoint.first == 4; }), 
       stopPoints.end()); 

您需要刪除從開始迭代器的範圍內std::remove_if返回到矢量,而不是僅單個元件的端部。

「爲什麼?」

  • std::remove_if互換元素周圍的載體內,以把不向容器開頭的謂詞匹配的所有元素。

    • 然後,它返回指向第一謂詞匹配元件迭代器。

    • std::vector::erase需要擦除範圍從返回迭代向量的末端開始,以除去匹配謂詞所有元素。


更多信息:Erase-remove idiom (Wikipedia)

+0

謝謝你,我花了一個小時在這個頭上撓了撓頭。 :) – omegasbk

5

std::vector::erase具有兩個重載的方法:

iterator erase(const_iterator pos); 
iterator erase(const_iterator first, const_iterator last); 

第一種方法只有在pos移除元件,而第二個刪除範圍[first, last)

由於您在通話中忘記了last迭代器,因此第一個版本通過超負荷分辨率進行選擇,並且您僅刪除第一對移至末端std::remove_if。你需要這樣做:

stopPoints.erase(std::remove_if(stopPoints.begin(), 
           stopPoints.end(), 
           [&](const stopPointPair stopPoint)-> bool { return stopPoint.first == 4; }), 
       stopPoints.end()); 

擦除刪除成語工作原理如下:假設你有一個載體{2, 4, 3, 6, 4},你要刪除的4

std::vector<int> vec{2, 4, 3, 6, 4}; 
auto it = std::remove(vec.begin(), vec.end(), 4); 

威爾通過將「除去」值放在最後(最終沒有指定值AB(如同值移動了012),將矢量轉換成),這就是爲什麼你在你的例子中得到了6),並返回一個迭代器到A(「刪除」值的第一個)。

如果你這樣做:

vec.erase(it) 

std::vector::erase第一個重載選擇,你只能在it刪除值,這是A並獲得{2, 3, 6, B}

通過加入第二個參數:

vec.erase(it, vec.end()) 

第二過載被選擇,並且您擦除itvec.end(),這樣既AB之間值被擦除。