【问题标题】:Removing elements marked for removal with Ranges-V3使用 Ranges-V3 移除标记为移除的元素
【发布时间】:2021-08-21 23:32:08
【问题描述】:

我有两个向量:

struct MyData{
     double value; 
};
std::vector<int> remove_flags = {0, 1, 0, 0, 0, 0, 1, 0};
std::vector<MyData> data =      {{},{},{},{},{},{},{},{}}; 

remove_flags 向量包含一个标志数组,其大小与data 完全相同,每个标志为 0 或 1,其中 1 表示应删除数据。

我想使用remove_flags 从data 中删除元素,即执行擦除删除习惯用法,但根据remove_flags 中的值进行擦除。最终结果应该是 data 并删除了元素,希望 remove_flags 删除了相同的元素。

手动执行此操作很烦人,我想为此使用 Range-v3。我目前使用的是 C++17。

查看文档后,我认为我没有找到解决方案,我能想到的最接近的方法是:

auto result = ranges::views::zip(remove_flags, data) | ranges::actions::remove_if([](std::pair<const int&, const MyData&> pair){
    return pair.first != 0;
});

remove_flags.erase(result.first, remove_flags.end());
data.erase(result.second, data.end());

但操作无法对视图 zip 进行操作,因此无法编译。如果我将ranges::actions::remove_if 切换为ranges::views::remove_if,则会返回一个奇怪的视图对象,大概是一个实际上没有对两个向量执行std::remove 等效操作的对象。

我可以使用contaner_to,但这会涉及到副本,我不想为了方便而支付这种不必要的罚款。 I've seen what I want accomplished in boost 其中实际的 zip 对迭代器可用于返回两个单独的删除结果。

这种模式在 Range-v3 中是否可行?

【问题讨论】:

  • 您是否真的想要std::vector 的结果?风景还不够吗?
  • @Enlico 请澄清您的问题,我在帖子中没有提到或演示“结果的标准向量”。事实上,我的例子不可能展示这一点,因为我说result.first 和result.second
  • 你的 sn-p 的最后两行表明你改变了data 和remove_flags,所以我认为假设你以后想使用 那些 是公平的,即这两个 std::vectors 包含您想要实现的“输出/结果/效果”。这就是您在帖子中“提到”您希望代码结果出现在 std::vector 中的地方(result,而不是 result,就像在我的之前的评论)。但是,让我们换一种说法:你的例子不是minimal reproducible example;你能把它变成一个还是用文字描述代码的期望结果/结果/效果是什么?
  • @Enlico 上面的例子现在代表一个 MVCE,我已经澄清了我想要的。请注意,标题与我的帖子没有分开,并且 boost 示例(第一部分)有效地给出了我想要的内容,只是没有范围语法。
  • 感谢您的澄清。我现在已经删除了我的答案,因为目前这显然不是一个好的答案。目前我没有任何想法。我很想知道为什么你需要移除原位的元素,而仅仅看到它们是不够的。

标签: c++ c++17 range-v3 erase-remove-idiom


【解决方案1】:

对现有范围的急切操作是算法的领域。唯一略 这里棘手的一点是将迭代器恢复到向量中,因为zip 并没有为您提供获取这些的直接方法。所以改为使用新的结束和范围开始之间的距离来恢复它们:

auto z = ranges::views::zip(remove_flags, data);
auto e = ranges::remove_if(z, [](auto&& r){ return r.first; });
data.erase(data.begin() + (e - z.begin()), data.end());
remove_flags.erase(remove_flags.begin() + (e - z.begin()), remove_flags.end());

Demo.

【讨论】:

    猜你喜欢
    • 2020-08-08
    • 2019-05-27
    • 2013-02-07
    • 2013-04-22
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多