从矩阵中删除零行(优雅的方式)
Removing zero rows from a Matrix (elegant way)
我有一个矩阵,有一些零行。我想删除零行。矩阵为Nx3。我所做的很简单。我创建std::vector
,其中每三个元素代表一行,然后我将其转换为Eigen::MatrixXd
。是否有一种优雅的方法来删除零行?
#include <iostream>
#include <vector>
#include <Eigen/Dense>
Eigen::MatrixXd VecToMat(const std::vector<double> vec)
{
int rows(vec.size()/3) , cols(3);
Eigen::MatrixXd temp( rows , cols);
int count(0);
for ( int i(0); i < rows; ++i)
{
temp(i,0) = vec[count];
temp(i,1) = vec[count+1];
temp(i,2) = vec[count+2];
count += 3;
}
return temp;
}
Eigen::MatrixXd getNewMat(Eigen::MatrixXd& Z)
{
std::vector<double> vec;
for ( int i(0); i < Z.rows(); ++i)
{
if ( (Z(i,0) && Z(i,1) && Z(i,2)) != 0 ){
vec.push_back(Z(i,0));
vec.push_back(Z(i,1));
vec.push_back(Z(i,2));
}
}
Eigen::MatrixXd temp = VecToMat(vec);
return temp;
}
int main()
{
Eigen::MatrixXd Z(5,3);
Z.setOnes();
Z(0,0) = 0;
Z(0,1) = 0;
Z(0,2) = 0;
Z(1,0) = 0;
Z(1,1) = 0;
Z(1,2) = 0;
Z(2,0) = 0;
Z(2,1) = 0;
Z(2,2) = 0;
std::cout << Z << std::endl << std::endl;
std::cout << getNewMat(Z) << std::endl;
std::cin.get();
return 0;
}
我觉得这是一个非常优雅的完整实现。请注意,此方法不保留非零规则的顺序,这可能不是您想要的,但在复杂性和代码行数方面都更有效:
void removeZeroRows(Eigen::MatrixXd& mat)
{
Matrix<bool, Dynamic, 1> empty = (mat.array() == 0).rowwise().all();
size_t last = mat.rows() - 1;
for (size_t i = 0; i < last + 1;)
{
if (empty(i))
{
mat.row(i).swap(mat.row(last));
empty.segment<1>(i).swap(empty.segment<1>(last));
--last;
}
else
++i;
}
mat.conservativeResize(last + 1, mat.cols());
}
基本上你可以遵循这样的伪代码:
- get N = rows, M = columns
- 遍历每个N
- 如果N[0] = 0,迭代第一个非零的行
- if N[0] = 0 &&. .,,N[m] = 0
- 删除行
删除单行:
void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove) {
unsigned int numRows = matrix.rows() - 1;
unsigned int numCols = matrix.cols();
unsigned int rowPos = numRows - rowToRemove;
if( rowToRemove < numRows ) {
matrix.block(rowToRemove, 0, rowPos, numCols) = matrix.block(rowToRemove + 1, 0, rowPos,numCols);
}
matrix.conservativeResize(numRows, numCols);
}
将每个非空行保存为一个向量,然后创建一个新的矩阵
vector<block> buffer; //not sure of the type name for the rows
VectorXd zero(3); //or appropriate comparable type
for(int i = 0; i < Z.rows(); i++){ //note: possibly a function call each time
if(Z.row(i) != zero)
//if((Z.row(i) != 0).any()) //broadcasting comparison?
buffer.push_back(Z.row(i));
}
MatrixXd return_value(buffer.size(), 3);
for(int i = buffer.size(); i --> 0;)
return_value.row(i) = buffer[i];
return return_value;
警告:调整旧文件的大小而不是创建新文件可能会在保存之前擦除内容。
我不能从这里读文档,所以你必须自己看看你可以在块对象上做什么样的比较操作。作为最后的结果,尝试row.any()
(更快?)或row.squaredNorm() == 0
。
相关文章:
- 是否可以在 QAbstractItemModel 中返回正数行数和零列数?
- 打印从SQLite3数据库检索的数据C++与命令行中相同的方式
- 如果第一个元素包含任何零,则我的程序以不希望的方式运行
- 文件追加的方式是,它在每次保存C++后结束行
- 为什么我的代码在添加不相关的代码行后工作方式不同?
- C 结构具有CHAR数组以不寻常的方式初始化为零
- 如何控制 clang 格式新行中 lessless 的对齐方式
- 在 Windows 命令行中运行.exe在使用 2 种相同方式执行时会产生不同的输出
- 以编程方式输入新行
- 用零填充矩阵行的问题
- 犰狳:从稀疏矩阵中获取稀疏行向量的非零位置
- 对齐方式与指针中尾随零的数量有何关系
- 是否可以更改 Xcode 缩进注释行的方式
- Arduino和Visual Studio C ,2方式串行通信
- 包含零行和 1000 列的矩阵
- 从文件读取后,输出中的额外零行
- 通过串行方式在Arduino和PC之间传递变量的最佳方式
- 从矩阵中删除零行(优雅的方式)
- if(result==NULL)总是返回false,即使查询返回零行也是如此
- C++应用程序只有在关闭时才以串行方式发送数据