C++ 从std::vector中删除任意项目列表<;标准::向量<;T>&燃气轮机;
我有一个向量向量,代表一个数组。我希望高效地删除行(以最小的复杂性和分配) 我考虑过构建一个新的向量向量,只复制未删除的行,使用移动语义,如下所示:C++ 从std::vector中删除任意项目列表<;标准::向量<;T>&燃气轮机;,c++,c++11,vector,move-semantics,erase-remove-idiom,C++,C++11,Vector,Move Semantics,Erase Remove Idiom,我有一个向量向量,代表一个数组。我希望高效地删除行(以最小的复杂性和分配) 我考虑过构建一个新的向量向量,只复制未删除的行,使用移动语义,如下所示: //std::vector<std::vector<T> > values is the array to remove rows from //std::vector<bool> toBeDeleted contains "marked for deletion" flags for each
//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);
//std::vector values是要从中删除行的数组
//std::vector toBeDeleted包含每行的“标记为删除”标志
//计算新的剩余行数
无符号整数newNumRows=0;
对于(unsigned int i=0;i这可以使用常规的变体来解决,在std::remove_中有一个lambda,如果
,它在要删除的索引的迭代器范围内查找当前行的索引:
#include <algorithm> // find, remove_if
#include <iostream>
#include <vector>
template<class T>
using M = std::vector<std::vector<T>>; // matrix
template<class T>
std::ostream& operator<<(std::ostream& os, M<T> const& m)
{
for (auto const& row : m) {
for (auto const& elem : row)
os << elem << " ";
os << "\n";
}
return os;
}
template<class T, class IdxIt>
void erase_rows(M<T>& m, IdxIt first, IdxIt last)
{
m.erase(
std::remove_if(
begin(m), end(m), [&](auto& row) {
auto const row_idx = &row - &m[0];
return std::find(first, last, row_idx) != last;
}),
end(m)
);
}
int main()
{
auto m = M<int> { { 0, 1, 2, 3 }, { 3, 4, 5, 6 }, { 6, 7, 8, 9 }, { 1, 0, 1, 0 } };
std::cout << m << "\n";
auto drop = { 1, 3 };
erase_rows(m, begin(drop), end(drop));
std::cout << m << "\n";
}
#包括
注意:因为从C++11开始,std::vector
具有移动语义,所以在std::vector
中使用简单的指针操作来移动行,而不考虑类型T
(不过,如果要删除列,情况会大不相同!).为什么不直接使用std::remove\u if
?我严重怀疑您的实现是否更快或使用更少的内存,只需在滚动您自己的实现之前进行概要分析。如果您不进行测量,您只是在猜测。嗯,remove\u if作为参数,它会告诉您是否仅基于项值删除项。我可以没有标记项目本身,我只有一个要删除的索引的bool表。如果您可以在这里执行std::vec;std::vector 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++]}虽然我不建议设置旗标数组,但是不要设置标志,考虑在最后用最后一个仍然好的元素来交换元素,并保持一个索引,之后所有元素都需要被移除。然后,你要做的就是调用<代码>调整大小< /代码>来进行任何实际的移除。特定顺序您还可以使用std::vector rows;
跟踪元素的标志(我不知道为什么我一直重复std::
说vector rows;
不会让任何人感到困惑).cute!顺便问一句,你的main中的drop
类型是什么?@Walter它是std::initializer\u list
,其中std::begin()
和std::end()
的工作方式与各种标准容器相同。你能解释一下auto const row\u idx=&row-&m[0];
?@galinette是的,它将行索引计算为第一行和当前行地址之间的差。@TemplateRex:row和m[0]是迭代器,对吗?所以row_idx是迭代器上两个指针之间的差??
#include <algorithm> // find, remove_if
#include <iostream>
#include <vector>
template<class T>
using M = std::vector<std::vector<T>>; // matrix
template<class T>
std::ostream& operator<<(std::ostream& os, M<T> const& m)
{
for (auto const& row : m) {
for (auto const& elem : row)
os << elem << " ";
os << "\n";
}
return os;
}
template<class T, class IdxIt>
void erase_rows(M<T>& m, IdxIt first, IdxIt last)
{
m.erase(
std::remove_if(
begin(m), end(m), [&](auto& row) {
auto const row_idx = &row - &m[0];
return std::find(first, last, row_idx) != last;
}),
end(m)
);
}
int main()
{
auto m = M<int> { { 0, 1, 2, 3 }, { 3, 4, 5, 6 }, { 6, 7, 8, 9 }, { 1, 0, 1, 0 } };
std::cout << m << "\n";
auto drop = { 1, 3 };
erase_rows(m, begin(drop), end(drop));
std::cout << m << "\n";
}