标签: erase-remove-idiom

使用 Ranges-V3 移除标记为移除的元素

我有两个向量:

struct MyData{
     double value; 
};
std::vector<int> remove_flags = {0, 1, 0, 0, 0, 0, 1, 0};
std::vector<MyData> data =      {{},{},{},{},{},{},{},{}}; 
Run Code Online (Sandbox Code Playgroud)

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

我想用来remove_flagsdata原地删除元素,即执行擦除删除习语,但根据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());
Run Code Online (Sandbox Code Playgroud)

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

可以使用,contaner_to …

c++ erase-remove-idiom range-v3 c++17

7
推荐指数
1
解决办法
195
查看次数

提升绑定编译错误

class A
{
   bool OutofRange(string& a, string& b, string c);
   void Get(vector <string>& str, string& a, string& b);
}

void A::Get(vector <string>& str, string& a, string& b)
{
   str.erase(
            std::remove_if (str.begin(), str.end(), BOOST_BIND(&A::OutOfRange, a, b, _1)),
            str.end()
            );
}
Run Code Online (Sandbox Code Playgroud)

我收到的错误如下:

 Error 7 error C2825: 'F': must be a class or namespace when followed by '::' File:bind.hpp
 Error 8 error C2039: 'result_type' : is not a member of '`global namespace'' t:\3rdparty\cpp\boost\boost-1.38.0\include\boost\bind.hpp 67 
Run Code Online (Sandbox Code Playgroud)

有人能告诉我我做错了什么吗?

c++ boost boost-bind erase-remove-idiom

6
推荐指数
1
解决办法
7643
查看次数

从向量中删除项目,并改变那些被删除的项目

我有一个std::vector<std::shared_ptr<Foo>>我想删除的项目- 删除匹配某些谓词的项目.删除的对象应该有一个方法,该方法设置一些状态以供其他地方使用.

当返回true时,我是否有理由不在谓词函数中执行此操作?感觉有点像混合问题,但我能想到的唯一选择似乎更加丑陋.

c++ erase-remove-idiom c++11

6
推荐指数
1
解决办法
198
查看次数

在擦除 - 删除习语中使用UnaryPredicate的否定

请考虑以下情形:

bool is_odd(int i)
{
    return (i % 2) != 0;  
}
int main()
{
    // ignore the method of vector initialization below.
    // assume C++11 is not to be used.
    std::vector<int> v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::vector<int> v2 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    // removes all odd numbers, OK
    v1.erase( std::remove_if(v1.begin(), v1.end(), is_odd), v1.end() );

    // remove all even numbers
    v2.erase( std::remove_if(v2.begin(), …
Run Code Online (Sandbox Code Playgroud)

c++ erase-remove-idiom c++03

6
推荐指数
2
解决办法
132
查看次数

如何模拟remove_unless

我有代码删除std::vector<int>少于一些的所有元素int limit.我写了一些部分应用lambdas的函数:

auto less_than_limit = [](int limit) {
  return [=](int elem) {
    return limit > elem;
  };
};

auto less_than_three = less_than_limit(3);
Run Code Online (Sandbox Code Playgroud)

当我测试它时std::vector<int> v{1,2,3,4,5};,我得到了预期的结果:

for(auto e: v) {
  std::cout << less_than_three(e) << " ";
}
// 1 1 0 0 0
Run Code Online (Sandbox Code Playgroud)

我可以轻松删除少于三个的所有元素:

auto remove_less_than_three = std::remove_if(std::begin(v), std::end(v), less_than_three);

v.erase(remove_less_than_three, v.end());

for(auto e: v) {
  std::cout << e << " ";
}
// 3 4 5
Run Code Online (Sandbox Code Playgroud)

如何使用less_than_three?删除大于或等于3的元素?

我试过包装less_than_threestd::not1,却得到了错误:

/usr/local/Cellar/gcc/5.3.0/include/c++/5.3.0/bits/stl_function.h:742:11: …
Run Code Online (Sandbox Code Playgroud)

c++ erase-remove-idiom c++11 c++14

6
推荐指数
2
解决办法
410
查看次数

根据索引删除矢量元素

我想基于索引删除向量的元素,比如所有偶数索引元素.我已经阅读了关于擦除删除习惯用法,但看不到如何应用它.这是我试过的:

    vector<int> line;
    line.reserve(10);
    for(int i=0;i<10;++i)
    {
      line.push_back(i+1);
    }
    for(unsigned int i=0;i<line.size();++i)
    {
      //remove the even indexed elements
      if(i%2 == 0)
      {
        remove(line.begin(),line.end(),line[i]);
      }
    }
line.erase( line.begin(),line.end() );
Run Code Online (Sandbox Code Playgroud)

这会擦除整个矢量.我希望只删除已删除算法标记的元素.

然后我尝试了这个

for(unsigned int i=0;i<line.size();++i)
    {
      //remove the even indexed elements
      if(i%2 == 0)
      {
        line.erase( remove(line.begin(),line.end(),line[i]),line.end() );
      }
    }
Run Code Online (Sandbox Code Playgroud)

由于在移除时存在问题,这再次不起作用,索引似乎在迭代矢量时移位.应该采取什么样的正确方法来实现这一目标.

c++ stl vector erase-remove-idiom

5
推荐指数
2
解决办法
7694
查看次数

为什么擦除删除习语不适用于反向迭代器

我的目标是尝试解决这个问题:从 end 中删除向量中的所有空元素。使用擦除删除成语。

这个想法是在给定std::vector<std::string>的字符串a中删除从末尾开始的所有元素,这些元素是空的(等于空白)。当发现非空元素时,应停止删除元素。

例子:

vec = { " ", "B", " ", "D", "E", " ", " ", " " };
Run Code Online (Sandbox Code Playgroud)

移除后:

vec = { " ", "B", " ", "D", "E"};
Run Code Online (Sandbox Code Playgroud)

这是我尝试的解决方案:

#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& …
Run Code Online (Sandbox Code Playgroud)

c++ base stdvector erase-remove-idiom stl-algorithm

5
推荐指数
1
解决办法
682
查看次数

是否有一种安全(定义的行为)方法来使用 STL 来减少基于向量索引有效过滤向量的样板?

我经常发现自己想要根据向量的索引而不是值来过滤向量。

auto some_values = std::vector{1, 0, 4, 6, 2};

// Somewhere I figure out which items to remove.
// This may be from user interaction or something
// nothing to do with the original values:
const auto removing = std::vector<bool>{0, 0, 1, 0, 1};
Run Code Online (Sandbox Code Playgroud)

erase_if所以,我很想像这样使用:

std::erase_if(some_values, [it = removing.begin()](auto) mutable {return *it++;});
Run Code Online (Sandbox Code Playgroud)

它似乎适用于 gcc 和 clang。但是, std::erase cppref 页面上似乎没有任何关于谓词调用顺序的内容,所以我认为这是未定义的行为?

与 相同的问题std::remove_if。请注意,压缩范围不适用于大多数压缩选项,因为通常生成的范围无法调整基础数据的大小。

使用 for 循环并创建数组的副本并不是太多的样板文件,但我目前正在将过滤器应用于一些低级代码,在这些代码中我无法复制所有数据。有些数据会很大,需要在这些过滤操作期间做出响应。

最坏的情况我可以添加这样的函数来解决问题:

template <class T, auto N, class Pred>
size_t …
Run Code Online (Sandbox Code Playgroud)

c++ stl erase-remove-idiom stl-algorithm c++20

5
推荐指数
1
解决办法
293
查看次数

为什么向量上的“调整大小删除”比“擦除删除”更快?

当谈到从容器中删除多个元素时,C++ 中有一个“擦除-删除”习惯用法,并且有关于替代“调整大小-删除”方式的讨论,例如,此处。人们说“擦除删除”比“调整大小删除”更好,但根据我的测试,后者在矢量上(稍微)更快。那么,当涉及到矢量时我应该使用“调整大小删除”吗?

这是我的基准测试代码:

#include <benchmark/benchmark.h>

#include <algorithm>
#include <functional>
#include <iostream>
#include <random>
#include <vector>

using namespace std;

constexpr size_t N_ELEMS = 1000000;
constexpr int MAX_VAL = N_ELEMS / 10;
constexpr int THRESH = MAX_VAL / 5 * 3;

static vector<int> generate_input() {
  vector<int> nums(N_ELEMS);

  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_int_distribution<> dist(0, N_ELEMS);

  std::generate(nums.begin(), nums.end(), std::bind(dist, std::ref(gen)));

  return std::move(nums);
}

static void bm_erase_remove(benchmark::State &state) {
  for (auto _ : state) {
    state.PauseTiming();
    auto nums = generate_input();
    state.ResumeTiming();
    nums.erase(std::remove_if(nums.begin(), …
Run Code Online (Sandbox Code Playgroud)

c++ benchmarking erase-remove-idiom

5
推荐指数
1
解决办法
270
查看次数

如何使擦除删除习惯用法与矢量元组一起使用?

我有一个成员为j,k和l的元组向量。我正在尝试适应“擦除删除”习惯用法,以便如果.k成员的值满足特定条件,则可以删除整个元组。

我尝试使用标准.erase(removeif())方法,其中谓词引用了元组成员位置,但被告知所涉及的向量类中没有成员“ k”。

vec_list_iter_exp_out.erase(
    std::remove_if(
        vec_list_iter_exp_out.begin(),
        vec_list_iter_exp_out.end(), 
        vec_list_iter_exp_out.k < 33), vec_list_iter_exp_out.end());
Run Code Online (Sandbox Code Playgroud)

我希望如果vec_list_iter_exp_out由以下假设值组成:

vec_list_iter_exp_out[0] = 5, 22, 9
vec_list_iter_exp_out[1] = 12, 31, 54
vec_list_iter_exp_out[2] = 17, 42, 0
vec_list_iter_exp_out[3] = 253, 3, 5
vec_list_iter_exp_out[4] = 65, 110, 24
Run Code Online (Sandbox Code Playgroud)

vec_list_iter_exp_out [2]和vec_list_iter_exp_out [4]的全部将被删除,然后vec_list_iter_exp_out将包括以下内容:

vec_list_iter_exp_out[0] = 5, 22, 9
vec_list_iter_exp_out[1] = 12, 31, 54
vec_list_iter_exp_out[2] = 253, 3, 5
Run Code Online (Sandbox Code Playgroud)

相反,我得到了上述编译错误。

任何帮助将不胜感激!

编辑:根据要求定义所讨论的向量。

struct TriStore
{
    double j,k,l;
};

std::vector<TriStore> vec_list_iter_exp_out;
Run Code Online (Sandbox Code Playgroud)

和用于插入的代码段(显然引用了其他功能和所拥有的功能,但这会占用太多空间)

    for(int z = 1; z <= iters; z++)
    {
        vec_iters.push_back(vec_list_iter_exp_out.size());
        for(int i = …
Run Code Online (Sandbox Code Playgroud)

c++ erase-remove-idiom

4
推荐指数
1
解决办法
117
查看次数