我在Eigen中有一个n x 3矩阵。我想通过按升序排序第1列中的值来重新排列第2和第3列的值。 例如,在排序之前:
1 4 6
-2 5 2
3 1 0
按照第1列值的升序排序后:
-2 5 2
1 4 6
3 1 0
我对如何解决这个问题感到茫然。我可以将每列读入一个向量并使用std :: sort对列1向量进行排序但是我无法看到如何在第1列中为第1列中的排序值保留相应的值.n的值已知并且是固定的,如果这有任何帮助。
答案 0 :(得分:1)
这不是很漂亮,并且依赖于使用模板参数分离矩阵 - 但它可以工作。
#include <Eigen/Core>
#include <algorithm>
#include <vector>
// Simple little templated comparison functor
template <typename MatrixT>
bool compareRows(MatrixT a, MatrixT b) {
return a(0,0) < b(0,0);
}
// These are the 6 template arguments to every Eigen matrix
template <typename Scalar, int rows, int cols, int options, int maxRows, int maxCols>
Eigen::Matrix<Scalar, rows, cols, options, maxRows, maxCols> sortMatrix(
Eigen::Matrix<Scalar, rows, cols, options, maxRows, maxCols> target
) {
// Manually construct a vector of correctly-typed matrix rows
std::vector<Eigen::Matrix<Scalar, 1, cols>> matrixRows;
for (unsigned int i = 0; i < target.rows(); i++)
matrixRows.push_back(target.row(i));
std::sort(
matrixRows.begin(),
matrixRows.end(),
compareRows<Eigen::Matrix<Scalar, 1, cols>>
);
Eigen::Matrix<Scalar, rows, cols, options, maxRows, maxCols> sorted;
for (unsigned int i = 0; i < matrixRows.size(); i++)
sorted.row(i) = matrixRows[i];
return sorted;
}
值得庆幸的是,由于模板参数推断,您可以简单地将此类问题称为:
Eigen::Matrix3f myMatrix;
// Fill in contents here
Eigen::Matrix3f sorted = sortMatrix(myMatrix);
我几乎是肯定的,这是一种更优雅的方式,但我现在无法想到它。而且,因为它使用std::vector
,您需要使用-std=c++11
或更好的方式进行编译。
答案 1 :(得分:1)
基于second Option by xjcl,我创建了一个基于lambda的选项,可以轻松地将其包含在头文件中:
#include <Eigen>
#include <algorithm>
#include <vector>
void eigen_sort_rows_by_head(Eigen::MatrixXd& A_nx3)
{
std::vector<Eigen::VectorXd> vec;
for (int64_t i = 0; i < A_nx3.rows(); ++i)
vec.push_back(A_nx3.row(i));
std::sort(vec.begin(), vec.end(), [](Eigen::VectorXd const& t1, Eigen::VectorXd const& t2){ return t1(0) < t2(0); } );
for (int64_t i = 0; i < A_nx3.rows(); ++i)
A_nx3.row(i) = vec[i];
};
此选项还通过引用获取目标矩阵。不过,我想可以改善它,希望对您有所帮助:
此外,尽管Eigen发出警告,我们还是不能将auto用于自动模板推导吗?
答案 2 :(得分:1)
我已经实现了此功能,您需要:
#include <Eigen/Dense>
#include <Eigen/Core>
函数是:
Eigen::MatrixXd sortMatrix(const Eigen::MatrixXd &original_matrix) {
Eigen::MatrixXd sorted_matrix(original_matrix.rows(), original_matrix.cols());
Eigen::VectorXd sorted_rows = original_matrix.col(0);
Eigen::VectorXd::Index min_row;
for ( int i = 0; i < original_matrix.rows(); i++) {
sorted_rows.minCoeff(&min_row);
sorted_matrix.row(i) = original_matrix.row(min_row);
sorted_rows(min_row) = std::numeric_limits<double>::max();
}
return sorted_matrix;
}
该函数创建要在新向量中排序的矩阵第一列的副本。它将最小值复制到另一个矩阵中。复制后,该值将被销毁(向量中分配的最大值,因此不会再次识别为最小值),因此它将继续查找和排序最小值,直到所有辅助向量都没有原始值并且订购新矩阵。如果有两个完全相同的值,则不能保证将订购第二列,而只关注第一列。 它是一个O(n ^ 2)算法,因此随着矩阵大小的增加,效率会降低。 有关使用的命令的一些信息:
答案 3 :(得分:0)
我提出的最佳解决方案是将行复制到std::vector
然后继续排序:
#include <Eigen/Core>
#include <algorithm> // std::sort
#include <vector> // std::vector
bool compare_head(const Eigen::VectorXd& lhs, const Eigen::VectorXd& rhs)
{
return lhs(0) < rhs(0);
}
Eigen::MatrixXd sorted_rows_by_head(Eigen::MatrixXd A_nx3)
{
std::vector<Eigen::VectorXd> vec;
for (int64_t i = 0; i < A_nx3.rows(); ++i)
vec.push_back(A_nx3.row(i));
std::sort(vec.begin(), vec.end(), &compare_head);
for (int64_t i = 0; i < A_nx3.rows(); ++i)
A_nx3.row(i) = vec[i];
return A_nx3;
}