使用其范围版本从容器中删除元素的最佳方法

问题描述 投票:3回答:2

我在我的代码中遇到一个常见问题,我想在它满足谓词后从反向std :: vector中只删除一个元素。我知道有很多方法可以用range-v3来做到这一点,但我想出的每一种方式看起来都有点复杂。

这是目标向量v的一个例子:

std::vector v = { 1, 2, 3, 2, 4 };

结果需要是向量r:

std::vector r = { 1, 2, 3, 4 };

这将通过移除在反向遍历向量v时找到的前2个(通过lambda谓词“is_two”)来完成。

这是一个在vanilla C ++原始循环中的样子:

auto is_two = [](int a) { return a == 2; };

for (int i = v.size(); --i >= 0;) {

    if (is_two(v[i])) {

        v.erase(v.begin() + i);
        break;
    }
}

这是我的糟糕范围-v3版本:

namespace rs = ranges;
namespace rv = ranges::view;
namespace ra = ranges::action;

rs::for_each(v | rv::enumerate
               | rv::reverse
               | rv::filter([](auto i_e) { return i_e.second == 2; })
               | rv::take(1),

            [&](auto& i_e) { v.erase(v.begin() + i_e.first); });

理想情况下,我想知道是否有一些解决方案看起来像这样:

ra::remove_if(v | rv::reverse, is_two);

为了概括,我想知道如何使用容器,通过一些范围::视图操作来管道它,然后从原始容器中删除结果范围内的元素。

c++ range
2个回答
1
投票

由于似乎没有人提出更好的方法,我想提一下,为了你的利益,可以选择好的旧reverse_iterators。

vec.erase(std::prev(ranges::find_if(vec.rbegin(), vec.rend(), is_two).base()));

不可否认,这不是范围很广,但最不起作用。


1
投票

基于范围的for循环的主要目的是一致性。对每个元素执行相同的操作。

删除元素会破坏这种一致性。所以最好的解决方案是一个正常的for循环,你可以使用迭代器和中断。

当你有锤子时,一切看起来像钉子。不要将远程环路锤入正常环路。

© www.soinside.com 2019 - 2024. All rights reserved.