【问题标题】:How to remove the Nth element in a range?如何删除范围内的第 N 个元素?
【发布时间】:2021-10-28 18:14:44
【问题描述】:

我会写:

my_range | ranges::views::remove(3)

使用范围-v3 库,从范围my_range 中删除等于 3 的元素。这也可以在 C++20 中使用

my_range | std::views::filter([](auto const& val){ return val != 3; })

但是 - 如何删除 my_range位置 3 处的元素,将元素保留在位置 0、1、2、4、5 等?

【问题讨论】:

  • 我对您的问题进行了相当戏剧性的编辑,以简化它。如果您不喜欢,请随时撤消更改...
  • @einpoklum 您添加的 [remove] 标签当前正在被烧毁,实际上meta.stackoverflow.com/questions/408573
  • @einpoklum std::ranges::remove 是一种算法,而不是范围适配器——正如你可以从它不在 views:: 中的事实看出的那样
  • @Barry:对……但它仍然存在。也许它也应该在问题中提及?

标签: c++ c++20 range-v3 std-ranges


【解决方案1】:

这是一种方法:

#include <iostream>
#include <ranges>
#include <range/v3/view/take.hpp>
#include <range/v3/view/drop.hpp>
#include <range/v3/view/concat.hpp>

int main() {
    const auto my_range = { 10, 20, 30, 40, 50, 60, 70 };
 
    auto index_to_drop = 3; // so drop the 40
    auto earlier = my_range | ranges::views::take(index_to_drop - 1);
    auto later = my_range | ranges::views::drop(index_to_drop);
    auto both = ranges::views::concat(earlier, later);
    for (auto const & num : both) { std::cout << num << ' '; }
}

这将产生:

10 20 30 50 60 70

...没有 40。

看到它在Godbolt 上工作。虽然编译时间非常差。此外,concat() 不是 C++20 的一部分。也许在 C++23 中?

【讨论】:

    【解决方案2】:

    在 range-v3 中我能想到的最直接的方法是:

    auto remove_at_index(size_t idx) {
        namespace rv = ranges::views;
        return rv::enumerate
             | rv::filter([=](auto&& pair){ return pair.first != idx; })
             | rv::values;
    }
    

    用法如下:

    my_range | remove_at_index(3);
    

    enumerate(以及它更一般的表亲zip)不在 C++20 中,但希望在 C++23 中。

    【讨论】:

    • 想到了这个,想起了this question,但不记得使用ranges-v3很容易。谢谢和 +1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多