我正在写一个程序,它将读取一个字符串向量,如果它遇到一个值为“..”的元素,它将删除自己和前一个元素。(例如{“1”,“2”,“..",“3”}将转换为{“1”,“3”})我知道我可以使用循环和erase()等编写代码来实现这一点,但我想知道是否可以使用标准库容器函数(如remove_if(),for_each()等)来实现这一点,因为这会使我的代码看起来更干净。我已经看过了,但没有在标准库中找到任何删除/擦除这种风格的元素的东西。
erase()
remove_if()
for_each()
ni65a41a1#
**TLDR:**可以使用向量函数完成,但由于性能和可读性的原因,不建议在您的情况下使用。下面是你要求的代码,以及我推荐的代码。
我们先来说说你提到的功能:
我能找到的最适合您使用的函数是find_if()。它可以让你找到第一个满足向量中 predicate 的迭代器,如果没有找到,就返回向量的结束迭代器。这个函数利用了它:
find_if()
#include <string> #include <vector> #include <algorithm> void processvec(std::vector<std::string>& vec) { std::vector<std::string>::iterator found; while ((found = std::find_if(vec.begin(), vec.end(), [](std::string str) {return str == ".."; })) != vec.end()) { vec.erase(vec.erase(found - 1)); } }
简单解释一下:
但要注意两件事:
{"..", "1", "2"}
因此,我认为在您的情况下,坚持使用通常的循环迭代器将是一个更好的主意。下面是一个应该足够有效地完成这项工作的函数:
#include <string> #include <vector> #include <algorithm> void processvec(std::vector<std::string>& vec) { for (std::vector<std::string>::iterator it = vec.begin(); it != vec.end();) { if (*it == ".." && it != vec.begin()) it = vec.erase(vec.erase(it - 1)); else ++it; } }
我不确定这里的客观可读性如何,但我发现前一个函数比后一个函数更难阅读,因为前一个函数上堆积了太多东西。
1条答案
按热度按时间ni65a41a1#
**TLDR:**可以使用向量函数完成,但由于性能和可读性的原因,不建议在您的情况下使用。下面是你要求的代码,以及我推荐的代码。
我们先来说说你提到的功能:
remove_if()
:此函数删除所有满足 predicate 的元素,并返回新向量范围的迭代器。它不返回被移除元素的单个迭代器,因此不允许移除依赖于它们的元素。for_each()
:此函数允许您为vector中包含的每个元素运行一个函数。然而,如这里所示,函数将目标指向向量的每个元素的直接值,而不是迭代器。因此,不能擦除依赖于正在迭代的元素的元素。另外,在使用此函数迭代向量时,可能会导致从向量中删除元素的问题。我能找到的最适合您使用的函数是
find_if()
。它可以让你找到第一个满足向量中 predicate 的迭代器,如果没有找到,就返回向量的结束迭代器。这个函数利用了它:
简单解释一下:
但要注意两件事:
{"..", "1", "2"}
,就会发生错误,因为在第一个“..”之前没有元素。find_if()
函数每次被调用时都会遍历你的向量。因此,在一个有一千个元素的大规模向量上,只有最后几个元素实际上是“..”,那么数百个元素将被迭代多次而一无所获。因此,我认为在您的情况下,坚持使用通常的循环迭代器将是一个更好的主意。
下面是一个应该足够有效地完成这项工作的函数:
我不确定这里的客观可读性如何,但我发现前一个函数比后一个函数更难阅读,因为前一个函数上堆积了太多东西。