通过索引删除一组元素

Deleting a bunch of elements by their index?

本文关键字:一组 元素 索引 删除      更新时间:2023-10-16

我有一个

vector<int> myVector;

我有一个index列表要删除:

vector<size_t> deleteIndex;

哪种策略最有效地删除这些索引?

实际上一个不有效的解决方案是:

//> sort deleteindex
auto deleted= 0;
for(auto i=0;i<deleteIndex.size();i++ {
   myVector.erase(myVector.begin()+deleteIndex[i]-deleted);
   deleted++;
}

逐个从vector中擦除元素是非常低效的。这是因为对于每次擦除,必须将所有元素向下复制1,然后重新分配一个小1的向量。

应该使用擦除-删除习语。这个过程将通过移动后面的项来替换前面的项来删除项(它保持原始顺序)。在元素被删除后,它将执行一次擦除(这只是列表的末尾)来重新分配一个新向量,该向量小于n个元素(其中n是被删除的元素数)。

样本实现:

template <class _FwdIt, class _FwdIt2>
_FwdIt remove_by_index(_FwdIt first, 
                       _FwdIt last,
                       _FwdIt2 sortedIndexFirst, 
                       _FwdIt2 sortedIndexLast)
{
  _FwdIt copyFrom = first;
  _FwdIt copyTo = first;
  _FwdIt2 currentIndex = sortedIndexFirst;
  size_t index = 0;
  for (; copyFrom != last; ++copyFrom, ++index)
  {
    if (currentIndex != sortedIndexLast &&
        index == *currentIndex)
    {
      // Should delete this item, so don't increment copyTo
      ++currentIndex;
      print("%d", *copyFrom);
    }
    else
    {
      // Copy the values if we're at different locations
      if (copyFrom != copyTo)
        *copyTo = *copyFrom;
      ++copyTo;
    }
  }
  return copyTo;
}
示例用法:

#include <vector>
#include <algorithm>
#include <functional>
int main(int argc, char* argv[])
{
  std::vector<int> myVector;
  for (int i = 0; i < 10; ++i)
    myVector.push_back(i * 10);
  std::vector<size_t> deleteIndex;
  deleteIndex.push_back(3);
  deleteIndex.push_back(6);
  myVector.erase(
    remove_by_index(myVector.begin(), myVector.end(), deleteIndex.begin(), deleteIndex.end()), 
    myVector.end());
  for (std::vector<int>::iterator it = myVector.begin();
       it != myVector.end(); ++it)
  {
    printf("%d ", *it);
  }
  return 0;
}

要点:https://gist.github.com/eleven41/5746079
测试在这里:http://ideone.com/0qkDw5

如果允许对myVector重新排序,则只需遍历要删除的项,通过与最后一个元素交换并弹出它来删除它们。

如果您需要保持顺序,对deleteIndex容器进行排序,并通过移动其他元素来执行单个有序传递以删除元素。