【发布时间】:2014-05-24 11:57:35
【问题描述】:
我有一个向量向量,代表一个数组。我想有效地删除行,即以最小的复杂性和分配
我考虑过构建一个新的向量向量,仅复制未删除的行,使用移动语义,如下所示:
//std::vector<std::vector<T> > values is the array to remove rows from
//std::vector<bool> toBeDeleted contains "marked for deletion" flags for each row
//Count the new number of remaining rows
unsigned int newNumRows = 0;
for(unsigned int i=0;i<numRows();i++)
{
if(!toBeDeleted[i])
{
newNumRows++;
}
}
//Create a new array already sized in rows
std::vector<std::vector<T> > newValues(newNumRows);
//Move rows
for(unsigned int i=0;i<numRows();i++)
{
if(!toBeDeleted[i])
{
newValues[i] = std::move(values[i]);
}
}
//Set the new array and clear the old one efficiently
values = std::move(newValues);
这是最有效的方法吗?
编辑:我只是想我可以通过迭代地向下移动行来避免分配新数组,这可能会更有效,代码也更简单:
unsigned int newIndex = 0;
for(unsigned int oldIndex=0;oldIndex<values.size();oldIndex++)
{
if(!toBeDeleted[oldIndex])
{
if(oldIndex!=newIndex)
{
values[newIndex] = std::move(values[oldIndex]);
}
newIndex++;
}
}
values.resize(newIndex);
谢谢!
【问题讨论】:
-
你为什么不直接使用
std::remove_if?我严重怀疑您的实现是否更快或使用更少的内存,只需在滚动您自己的实现之前进行分析。如果你不测量,你只是在猜测。 -
好吧,remove_if 将一个函数作为参数,该函数告诉是否仅根据项目值删除项目。我不能自己标记项目,我只有一个要删除的索引的布尔表。在这里使用 remove_if 不是那么简单
-
你可以做
std::vector<int> vec; std::vector<bool> remVec; auto begin = std::begin(vec); auto end = std::end(vec); size_t idx = 0; std::remove_if(begin,end,[&idx,&remVec](const int& ){return remVec[idx++];});。尽管我建议首先不要使用标志数组。与其设置标志,不如考虑将元素与最后一个仍然完好的元素交换,并维护一个索引,之后所有元素都需要被删除。那么您所要做的就是致电resize进行任何实际删除。 -
哦,如果有特定的顺序,您还可以使用
std::vector<std::pair<std::vector<T>,bool>> rows;来跟踪元素的标志(我不知道为什么我一直重复std::说vector<pair<vector<T>,bool>> rows;不会真正混淆任何人)。
标签: c++ c++11 vector move-semantics erase-remove-idiom