为什么 erase-remove 习语不适用于反向迭代器
Why erase-remove idiom not working for reverse iterator
我的目标是尝试解决这个问题:Removing all empty elements in a vector from end。使用 erase-remove 习语。
想法是在给定的 std::vector<std::string>
个字符串中删除从末尾开始的所有空元素(等于 white-space)。当找到非空元素时,应该停止删除元素。
示例:
vec = { " ", "B", " ", "D", "E", " ", " ", " " };
移除后:
vec = { " ", "B", " ", "D", "E"};
这是我尝试过的解决方案:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <iterator>
int main()
{
std::vector<std::string> vec = { " ", "B", " ", "D", "E", " ", " ", " " };
bool notStop = true;
auto removeSpaceFromLast = [&](const std::string& element)-> bool
{
if(element != " " ) notStop = false;
return ( (element == " ") && (notStop) );
};
vec.erase(
std::remove_if(vec.rbegin(), vec.rend(), removeSpaceFromLast),
vec.rend() );
std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(std::cout,","));
return 0;
}
这给了我一个错误:
no matching function for call to std::vector<std::__cxx11::basic_string<char> >::erase(std::reverse_iterator<__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >, std::vector<std::__cxx11::basic_string<char> >::reverse_iterator)'|
然后我在这里阅读了 std::vector::erase()
的工作:
并更改了代码:
vec.erase(
std::remove_if(vec.rbegin().base(), vec.rend().base(), removeSpaceFromLast),
vec.rend().base() );
这次它编译了,但给了我输出=原始向量。
谁能解释一下:
- 为什么会这样?
- 如果可能的话,我们该如何解决?
您错拨了 base()
的电话。 remove_if
会将它找到的所有 spaces 从向量的末尾开始移动到开始部分(因为它会移动 spaces 从开始开始移动到结束,如果前向迭代器被使用)和 returns 迭代器指向要被擦除的序列的结束位置(即要保留的 space 的开始,因为我们反转了迭代器的含义),即:
" ", " ", " ", "B", " ", "D", "E"
然后,你必须从头开始擦除,即rend().base()
。
vec.erase(vec.rend().base(),
std::remove_if(vec.rbegin(), vec.rend(), removeSpaceFromLast).base()
);
我的目标是尝试解决这个问题:Removing all empty elements in a vector from end。使用 erase-remove 习语。
想法是在给定的 std::vector<std::string>
个字符串中删除从末尾开始的所有空元素(等于 white-space)。当找到非空元素时,应该停止删除元素。
示例:
vec = { " ", "B", " ", "D", "E", " ", " ", " " };
移除后:
vec = { " ", "B", " ", "D", "E"};
这是我尝试过的解决方案:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <iterator>
int main()
{
std::vector<std::string> vec = { " ", "B", " ", "D", "E", " ", " ", " " };
bool notStop = true;
auto removeSpaceFromLast = [&](const std::string& element)-> bool
{
if(element != " " ) notStop = false;
return ( (element == " ") && (notStop) );
};
vec.erase(
std::remove_if(vec.rbegin(), vec.rend(), removeSpaceFromLast),
vec.rend() );
std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(std::cout,","));
return 0;
}
这给了我一个错误:
no matching function for call to std::vector<std::__cxx11::basic_string<char> >::erase(std::reverse_iterator<__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >, std::vector<std::__cxx11::basic_string<char> >::reverse_iterator)'|
然后我在这里阅读了 std::vector::erase()
的工作:
并更改了代码:
vec.erase(
std::remove_if(vec.rbegin().base(), vec.rend().base(), removeSpaceFromLast),
vec.rend().base() );
这次它编译了,但给了我输出=原始向量。
谁能解释一下:
- 为什么会这样?
- 如果可能的话,我们该如何解决?
您错拨了 base()
的电话。 remove_if
会将它找到的所有 spaces 从向量的末尾开始移动到开始部分(因为它会移动 spaces 从开始开始移动到结束,如果前向迭代器被使用)和 returns 迭代器指向要被擦除的序列的结束位置(即要保留的 space 的开始,因为我们反转了迭代器的含义),即:
" ", " ", " ", "B", " ", "D", "E"
然后,你必须从头开始擦除,即rend().base()
。
vec.erase(vec.rend().base(),
std::remove_if(vec.rbegin(), vec.rend(), removeSpaceFromLast).base()
);