我有一个对象向量,想按值删除。但是,该值只会出现一次,而且我也不在乎排序。
很显然,如果这样的按值删除非常普遍,并且/或者数据集很大,那么向量就不是最佳的数据结构。但是,假设我确定情况并非如此。
要明确的是,如果我的代码是C,我将对以下内容感到满意:
void delete_by_value( int* const piArray, int& n, int iValue ) {
for ( int i = 0; i < n; i++ ) {
if ( piArray[ i ] == iValue ) {
piArray[ i ] = piArray[ --n ];
return;
}
}
}
使用std :: algos和容器方法的“现代成语”方法似乎是:
v.erase(std::remove(v.begin(), v.end(), iValue), v.end());
但是那应该慢得多,因为对于一个随机存在的元素,它是n / 2个移动并且n比较。我的版本是1步,n / 2比较。
在“现代习语”中,肯定有比擦除-删除习语更好的方法吗?如果不是,为什么呢?
答案 0 :(得分:2)
使用std::find
替换循环。从end
迭代器的前任中获取替换值,并将该迭代器用于该元素的erase
。由于此迭代器位于最后一个元素上,因此erase
很便宜。奖励:bool
返回以进行成功检查并template
结束int
。
template<typename T>
bool delete_by_value(std::vector<T> &v, T const &del) {
auto final = v.end();
auto found = std::find(v.begin(), final, del);
if(found == final) return false;
*found = *--final;
v.erase(final);
return true;
}
答案 1 :(得分:2)
在“现代习语”中,肯定有比擦除-删除习语更好的方法吗?
在标准库中,没有每种利基用例的现成功能。不稳定删除是未提供的功能之一。虽然已经proposed (p0041r0)一段时间了。同样,对于不包含重复项的向量的特殊情况,也没有特殊的算法版本。
因此,如果您想使用最佳算法,则需要自己实现算法。有std::find
个用于线性搜索。之后,您只需要从最后一个元素开始分配,最后将其弹出即可。
答案 2 :(得分:0)
如果减小向量的大小,std::vector::resize
的大多数实现将不会重新分配。因此,以下代码可能具有与C示例相似的性能。
void find_and_delete(std::vector<int>& v, int value) {
auto it = std::find(v.begin(), v.end(), value);
if (it != v.end()) {
*it = v.back();
v.resize(v.size() - 1);
}
}
答案 3 :(得分:0)
C ++的方式与std::vector
大致相同:
template <typename T>
void delete_by_value(std::vector<T>& v, const T& value) {
auto it = std::find(v.begin(), v.end(), value);
if (it != v.end()) {
*it = std::move(v.back());
v.pop_back();
}
}