如何用Eigen高效遍历矩阵中不在指定索引向量P内的行?
用Eigen高效修改矩阵中不在指定索引集合内的行
给定10×10的全1矩阵B,以及索引向量P = {1, 6, 3, 7, 5},需要修改不在P中的行(即索引0、2、4、8、9的行)的值,以下是两种高效实现方式:
方法一:基于排序+二分查找构造补集索引
适合P的元素数量较多的场景,通过二分查找快速判断行索引是否属于P,避免逐行遍历比对的冗余:
#include <Eigen/Dense> #include <vector> #include <algorithm> int main() { Eigen::MatrixXd B = Eigen::MatrixXd::Ones(10, 10); std::vector<int> P = {1, 6, 3, 7, 5}; // 对P排序,为二分查找做准备 std::sort(P.begin(), P.end()); // 筛选出不在P中的行索引 std::vector<Eigen::Index> complement_rows; for (Eigen::Index i = 0; i < B.rows(); ++i) { if (!std::binary_search(P.begin(), P.end(), static_cast<int>(i))) { complement_rows.push_back(i); } } // 转换为Eigen兼容的索引数组 Eigen::ArrayXi complement_idx(complement_rows.size()); for (size_t j = 0; j < complement_rows.size(); ++j) { complement_idx(j) = complement_rows[j]; } // 批量修改目标行(示例:将这些行全部设为0) B(complement_idx, Eigen::all) = 0.0; std::cout << B << std::endl; return 0; }
方法二:基于布尔标记构造目标索引
适合矩阵行数较少的场景,逻辑更直观,无需排序:
#include <Eigen/Dense> #include <vector> int main() { Eigen::MatrixXd B = Eigen::MatrixXd::Ones(10, 10); std::vector<int> P = {1, 6, 3, 7, 5}; // 初始化标记数组:默认所有行都需要修改 std::vector<bool> need_modify(B.rows(), true); // 标记P中的行为不需要修改 for (int idx : P) { need_modify[idx] = false; } // 收集需要修改的行索引 std::vector<Eigen::Index> target_rows; for (Eigen::Index i = 0; i < B.rows(); ++i) { if (need_modify[i]) { target_rows.push_back(i); } } // 转换为Eigen兼容的索引数组 Eigen::ArrayXi target_idx(target_rows.size()); for (size_t j = 0; j < target_rows.size(); ++j) { target_idx(j) = target_rows[j]; } // 批量修改目标行(可替换为你需要的操作) B(target_idx, Eigen::all) = 0.0; std::cout << B << std::endl; return 0; }
效率说明
两种方法的核心都是先构造目标行的索引集合,再通过Eigen的块操作B(target_idx, Eigen::all)批量赋值。这种方式比逐行循环修改效率更高,因为Eigen会利用向量化指令优化内存访问,减少循环开销。
内容的提问来源于stack exchange,提问作者苏茂江
相关产品推荐
相关产品推荐

