如何从给定另一个迭代器向量的向量中删除元素

时间:2015-02-19 18:27:00

标签: c++ c++11 stdvector

我有两个载体

vector<int> vint;
vector<vector<int>::iterator> viter;

删除vint中迭代器所在的viter中的所有元素的最佳方法是什么?目前,我的工作方式暂时转移到list

编辑:(更多背景)

这是我目前的代码。我希望我可以避免移动到列表并返回到载体

void foo(std::vector<Blah>& bvec)
{
  std::list<Blah> blist;
  std::move(bvec.begin(), bvec.end(), std::back_inserter(blist));
  bvec.clear();
  std::vector<std::list<Blah>::iterator> selectedElements;
  { 
     //Critical section which holds a mutex. Should be as fast as possible
     for(auto it = blist.begin(), it_end= blist.end(); it != it_end; ++it)
     {
        if(shouldElementBeRemoved(*it))
           selectedElements.push_back(it);
     }
  }
  for(auto& it: selectedElements)
  {
     if(shouldElementReallyBeRemoved(*it))
        blist.erase(it);
  }
  std::move(blist.begin(), blist.end(), std::back_inserter(bvec));
}

如果我可以直接从矢量中删除,可以在没有列表的情况下进行简化。

void foo(std::vector<Blah>& bvec)
{
  std::vector<std::vector<Blah>::iterator> selectedElements;
  { 
     //Critical section which holds a mutex. Should be as fast as possible
     for(auto it = bvec.begin(), it_end= bvec.end(); it != it_end; ++it)
     {
        if(shouldElementBeRemoved(*it))
           selectedElements.push_back(it);
     }
  }
  for(auto& it: selectedElements)
  {
     if(shouldElementReallyBeRemoved(*it))
        // bvect.erase(it);              //Not safe!
  }
}

3 个答案:

答案 0 :(得分:2)

这对我来说似乎做对了:

#include <algorithm>

  for (auto current = vint.end();
       current >= vint.begin();) {
    current--;
    if (any_of(
          viter.begin(),
          viter.end(),
          [current](std::vector<int>::iterator it) {
            return current == it;
          })) {
      vint.erase(current);
    }
  }

使用any_of允许迭代器向量未排序。

答案 1 :(得分:2)

你应该可以使用你的第二个片段进行一些小修改 - 而不是向前方向迭代selectedElements,然后向后移动。然后,对bvec.erase的调用永远不会使保留在selectedElements中的任何迭代器失效。

void foo(std::vector<Blah>& bvec)
{
  std::vector<std::vector<Blah>::iterator> selectedElements;
  selectedElements.reserve(bvec.size());  // avoid growing the vector while you hold a mutex lock

  { 
     //Critical section which holds a mutex. Should be as fast as possible
     for(auto it = bvec.begin(), it_end= bvec.end(); it != it_end; ++it)
     {
        if(shouldElementBeRemoved(*it))
           selectedElements.push_back(it);
     }
  }
  for(auto first = selectedElements.rbegin(),
           last  = selectedElements.rend();
           first != last;
           ++first)
  {
      if(shouldElementReallyBeRemoved(**first)) 
        bvec.erase(*first);
  }
}

Live demo

答案 2 :(得分:1)

也许这适合您的情况:

struct Blah
{
    bool deleted = false; // add a special field
    // other data
};

void foo(std::vector<Blah>& bvec)
{
    {
        //Critical section which holds a mutex. Should be as fast as possible
        // mark them quickly
        for(auto& b: bvec)
            if(shouldElementBeRemoved(b))
                b.deleted = true;
    }

    // remove them slowly
    for(auto i = bvec.begin(); i != bvec.end();)
    {
        if(i->deleted && shouldElementReallyBeRemoved(*i))
            i = bvec.erase(i);
        else
        {
            i->deleted = false;
            ++i;
        }
    }
}