我有一个双精度的一维特征数组(Eigen::Array<double,Dynamic,Dynamic>
),我想修改数组中的每个元素。但是,我不确定如何做到这一点。我考虑过这个:
Eigen::Array<double,Eigen::Dynamic,Eigen::Dynamic> arr1D;
// ...
// Threshold function:
arr1D.unaryExpr([](double& elem)
{
elem = elem < 0.0 ? 0.0 : 1.0;
}
);
但这看起来有点像黑客,因为Eigen Reference示例仅提供了.unaryExpr
的示例,其中它与一个返回值的仿函数一起使用(然后整个方法只返回一个不同的数组)。就我而言,我希望避免创建新阵列的需要。
我是Eigen的新手,所以我想我可能会在这里遗漏一些东西,感谢输入。
编辑:我知道我可以使用arr1D = arr1D >= 0.0
替换上述内容,但请注意,这只是一个示例
答案 0 :(得分:7)
.unaryExpr
将“view”返回给定函数转换的原始数据。它不会对原始数据进行转换。
您无法更改传递给转换函数的参数。您的代码只是因为您没有触发适当代码的模板实例化而编译的。如果将结果赋值给那么它就无法编译:
#include <Eigen/Dense>
int main()
{
using namespace Eigen;
ArrayXd x, y;
y = x.unaryExpr([](double& elem)
{
elem = elem < 0.0 ? 0.0 : 1.0;
}); // ERROR: cannot convert const double to double&
}
错误的确切位置在Eigen
内部:
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
{
return derived().functor()( derived().nestedExpression().coeff(index) );
// ^^^^^^^^^^^^^^^^^^^ - your lambda
}
我认为使用Eigen
进行就地的最简单方法是:
ArrayXd x = ArrayXd::Random(100);
x = x.unaryExpr([](double elem) // changed type of parameter
{
return elem < 0.0 ? 0.0 : 1.0; // return instead of assignment
});
unaryExpr
不会返回全新的数组/矩阵 - 但会返回特殊的临时对象,就像它一样。
答案 1 :(得分:0)
如果您的价值类型相对简单,那么Evgeny的答案是最好的。
但是,如果您想重新创建real()
和complex()
(访问Scalar
结构的部分内容),您可以使用const_cast<>
将其彻底破解,是real/complex()
实际上做的(截至v3.3.3):
(注意:此代码仅在C ++ 1y中测试过,但可以简化。)
struct Value {
double a{1.5};
int b{2};
};
// Savage. Use aforemention hack from scalar_real_ref_op.
struct get_mutable_a_direct {
double& operator()(const Value& v) const {
return const_cast<Value&>(v).a;
}
};
// ...
MatrixX<Value> X(2, 2);
auto X_am_direct = CwiseUnaryView<get_mutable_a_direct, MatrixX<Value>>(
X, get_mutable_a_direct());
X_am_direct.setConstant(20);
我还测试了一个快速包装器,将上面的内容简化为:
struct get_a_flex {
double& operator()(Value& v) const {
return v.a;
}
const double& operator()(const Value& v) const {
return v.a;
}
};
// Less? savage.
auto X_am = unaryExprFlex(X, get_a_flex());
X_am *= 10;
cout << X_ac << endl;
// Works.
const auto& Xc = X;
auto Xc_am = unaryExprFlex(Xc, get_a_flex());
// Xc_am.setConstant(20); // Fails as desired.
cout << Xc_am << endl;
您可以在此处查看代码段:unary_view_mutable.cc
注意:如果您想使用labmda,请务必指明通过auto&
返回引用:
auto X_bm = unaryExprFlex(X, [](Value& v) -> auto& { return v.b; });
cout << X_bm << endl;
X_bm.setConstant(10);
cout << X_bm << endl;