从std :: vector中的特定索引中删除

时间:2013-12-14 11:09:49

标签: c++ vector

假设我有一个带有5个元素的std :: vector,我需要删除索引1和3中的元素,这是最快的方法。标准库中是否有任何帮助方法可以为我做这个?

4 个答案:

答案 0 :(得分:7)

您可以使用erase功能。对于这个特定情况,你提到这样的事情:

myvector.erase (myvector.begin()+3);
myvector.erase (myvector.begin()+1);

会做到这一点。您必须为erase函数提供迭代器,我建议您阅读文档以供其使用。以上内容适用于您的情况。请注意,每次调用erase都会更改删除位置后剩余元素的索引,但内部数组元素将相对于删除的项目进行调整。

在回复你的评论时,你一次只能删除一个元素,除非它们是连续的索引,在这种情况下你可以使用基于范围的擦除版本作为开始和结束迭代器。 例如,如果要删除索引1,2和3,请使用

myvector.erase (myvector.begin()+1,myvector.begin()+4);

正如我已经提到的那样,你擦除之后的物品索引会相应地降档。这是不可避免的,因为数组中不能有“间隙”。

答案 1 :(得分:7)

这应该是使用std::move的相当有效的实现,并且只将每个元素移动一次。它要求在to_remove中删除索引以进行排序。

template<typename T>
  void remove_index(std::vector<T>& vector, const std::vector<int>& to_remove)
  {
    auto vector_base = vector.begin();
    std::vector<T>::size_type down_by = 0;

    for (auto iter = to_remove.cbegin(); 
              iter < to_remove.cend(); 
              iter++, down_by++)
    {
      std::vector<T>::size_type next = (iter + 1 == to_remove.cend() 
                                        ? vector.size() 
                                        : *(iter + 1));

      std::move(vector_base + *iter + 1, 
                vector_base + next, 
                vector_base + *iter - down_by);
    }
    vector.resize(vector.size() - to_remove.size());
  }

// Usage:
//
// std::vector<std::string> values = { "0", "1", "2", "3", "4", "5"};
// remove_index(values, { 1, 3 });

答案 2 :(得分:2)

如果要删除矢量中的某些任意元素,可以按照以下方式执行此操作

for ( int i : { 3, 1 } ) v.erase( std::next( v.begin(), i ) );

考虑初始化列表中的项目应按降序排列。

答案 3 :(得分:2)

这比逐个删除要快得多(尽管在某些情况下它仍然可以加速):

template<class It>
struct remover
{
    size_t *i;
    It *begin;
    It const *end;
    explicit remover(size_t &i, It &begin, It const &end) : i(&i), begin(&begin), end(&end) { }
    template<class T>
    bool operator()(T const &)
    {
        size_t &i = *this->i;
        It &begin = *this->begin;
        It const &end = *this->end;
        while (begin != end && *begin < i)  /* only necessary in case there are duplicate indices */
        { ++begin;  }
        bool const b = begin != end && *begin == i;
        if (b) { ++begin; }
        ++i;
        return b;
    }
};
template<class Container, class IndexIt>
IndexIt remove_indices(Container &items, IndexIt indices_begin, IndexIt const &indices_end)
{
    size_t i = 0;
    std::sort(indices_begin, indices_end);
    items.erase(std::remove_if(items.begin(), items.end(), remover<IndexIt>(i, indices_begin, indices_end)), items.end());
    return indices_begin;
}
int main()
{
    std::vector<int> items(100);
    std::vector<size_t> indices;
    indices.push_back(5);
    indices.push_back(1);
    remove_indices(items, indices.begin(), indices.end());
}