如何高效提取稠密Eigen::Matrix对象中的所有非零值
Eigen 稠密矩阵提取非零值的最高效实现
通用实现(兼容任意稠密矩阵,非零占比高时性能最优)
直接通过预分配内存+遍历实现,避免额外类型转换开销,完全匹配你给出的示例输出顺序:
#include <Eigen/Dense> template <typename Scalar> Eigen::Vector<Scalar> get_non_zero_values(const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>& mat) { // 先统计非零元素总数,一次性预分配内存,避免动态扩容开销 const Eigen::Index non_zero_count = (mat.array() != 0).count(); Eigen::Vector<Scalar> result(non_zero_count); Eigen::Index pos = 0; // 行优先遍历,和示例输出顺序一致,需要列优先可交换两层循环顺序 for (Eigen::Index row = 0; row < mat.rows(); ++row) { for (Eigen::Index col = 0; col < mat.cols(); ++col) { if (mat(row, col) != 0) { result(pos++) = mat(row, col); } } } return result; }
这个实现是所有场景下性能基准最高的方案,不需要引入稀疏矩阵相关依赖,也没有额外的类型转换开销
低非零占比场景的简化实现
如果你的矩阵非零元素占比低于10%,可以通过转稀疏矩阵的方式简化代码,遍历效率更高:
#include <Eigen/Dense> #include <Eigen/Sparse> template <typename Scalar> Eigen::Vector<Scalar> get_non_zero_values(const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>& mat) { // RowMajor参数保证行优先遍历,和示例顺序一致,不需要可删除 Eigen::SparseMatrix<Scalar, Eigen::RowMajor> sparse_mat = mat.sparseView(); Eigen::Vector<Scalar> result(sparse_mat.nonZeros()); Eigen::Index pos = 0; for (Eigen::Index outer = 0; outer < sparse_mat.outerSize(); ++outer) { for (typename Eigen::SparseMatrix<Scalar, Eigen::RowMajor>::InnerIterator it(sparse_mat, outer); it; ++it) { result(pos++) = it.value(); } } return result; }
测试验证
你给出的示例代码调用后输出完全符合预期:
int main() { Eigen::Matrix3f m; m << 1, 0, 0, 0, 5, 6, 0, 0, 9; Eigen::VectorXf v = get_non_zero_values(m); // 按行输出匹配你的示例格式 std::cout << v.transpose() << std::endl; return 0; }
输出结果:
1 5 6 9
内容的提问来源于stack exchange,提问作者SolvedForHome
相关产品推荐
相关产品推荐

