【发布时间】:2023-03-21 17:31:01
【问题描述】:
我有一个项目向量 items,以及一个应该从 items 中删除的索引向量:
std::vector<T> items;
std::vector<size_t> indicesToDelete;
items.push_back(a);
items.push_back(b);
items.push_back(c);
items.push_back(d);
items.push_back(e);
indicesToDelete.push_back(3);
indicesToDelete.push_back(0);
indicesToDelete.push_back(1);
// given these 2 data structures, I want to remove items so it contains
// only c and e (deleting indices 3, 0, and 1)
// ???
知道每次删除都会影响indicesToDelete 中的所有其他索引,执行删除的最佳方法是什么?
几个想法是:
- 将
items复制到一个新的向量,一次一项,如果索引在indicesToDelete中则跳过 - 迭代
items并为每次删除,递减indicesToDelete中具有更大索引的所有项目。 - 首先对
indicesToDelete进行排序,然后对indicesToDelete进行迭代,每次删除都会增加一个indexCorrection,该indexCorrection会从后续索引中减去。
似乎我在想这样一个看似微不足道的任务。有更好的想法吗?
编辑这是解决方案,基本上是 #1 的变体,但使用迭代器来定义要复制到结果的块。
template<typename T>
inline std::vector<T> erase_indices(const std::vector<T>& data, std::vector<size_t>& indicesToDelete/* can't assume copy elision, don't pass-by-value */)
{
if(indicesToDelete.empty())
return data;
std::vector<T> ret;
ret.reserve(data.size() - indicesToDelete.size());
std::sort(indicesToDelete.begin(), indicesToDelete.end());
// new we can assume there is at least 1 element to delete. copy blocks at a time.
std::vector<T>::const_iterator itBlockBegin = data.begin();
for(std::vector<size_t>::const_iterator it = indicesToDelete.begin(); it != indicesToDelete.end(); ++ it)
{
std::vector<T>::const_iterator itBlockEnd = data.begin() + *it;
if(itBlockBegin != itBlockEnd)
{
std::copy(itBlockBegin, itBlockEnd, std::back_inserter(ret));
}
itBlockBegin = itBlockEnd + 1;
}
// copy last block.
if(itBlockBegin != data.end())
{
std::copy(itBlockBegin, data.end(), std::back_inserter(ret));
}
return ret;
}
【问题讨论】:
-
#3 应该是“先对
indeciesToDelete排序,然后按相反的顺序删除。那就不需要更正了。虽然,它仍然是缓慢的答案。 -
项目是否只有少量元素。或者它可以是巨大的吗?复制 T 的成本是多少?销毁 T 的成本是多少? T 是否可移动(如 C++11 中的可移动)?
-
T 是一个小结构,包含一对
std::strings 和一些整数。通常我们会删除少量元素。我将使用下面发布的反向排序解决方案。谢谢大家。 -
一定会喜欢你选择列表而不是矢量的时代
-
你关心保持向量中元素的顺序吗?