如何从Eigen中的索引向量中提取(Eigen :: Vector)子向量?

use*_*533 9 c++ eigen eigen3

假设我有

Eigen::VectorXd x; //{1,2,3,4,5,6,7,8}
Run Code Online (Sandbox Code Playgroud)

Eigen::VectorXd ind_vec; //{0,2,4,5}
Run Code Online (Sandbox Code Playgroud)

有没有办法轻松提取ind_vecx 的元素?

就像是:

x.extract(ind_vec) returning {1, 3, 5, 6}
Run Code Online (Sandbox Code Playgroud)

Jav*_*i V 9

由于目前的答案对我来说不满意,我用Google搜索了一下,我在Eigen文档中找到了这个教程.

#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::ArrayXf v(6);
  v << 1, 2, 3, 4, 5, 6;
  cout << "v.head(3) =" << endl << v.head(3) << endl << endl;
  cout << "v.tail<3>() = " << endl << v.tail<3>() << endl << endl;
  v.segment(1,4) *= 2;
  cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl;
}
Run Code Online (Sandbox Code Playgroud)

将输出:

v.head(3) =
1
2
3

v.tail<3>() = 
4
5
6

after 'v.segment(1,4) *= 2', v =
 1
 4
 6
 8
10
 6
Run Code Online (Sandbox Code Playgroud)

我没有用矢量测试它,但我想也应该是可能的.

  • 这仅适用于连续索引,不能回答OP的问题(Eigen :: VectorXd ind_vec; // {0,2,4,5}) (2认同)

ɲeu*_*urɳ 9

在 C++ 11(及更高版本)中,请执行以下操作:

 ind_vec.unaryExpr(x);
Run Code Online (Sandbox Code Playgroud)

您可以使用 ,unaryExpr(Functor)因为我们采用索引数组并将函子应用于数组的每个元素。结果类型将具有与索引数组相同的维度。对于函子,我们需要一个带有运算符的对象:

 Scalar operator() (Index index) const {
     return x[index];
 }
Run Code Online (Sandbox Code Playgroud)

碰巧,Eigen::Matrix已经有这样的运营商了。这是一个完整的例子:

Eigen::VectorXd x(8);  x << 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8;
Eigen::Array4i ind_vec(0,2,4,5);

// result has dimensions as ind_vec matrix/array, and scalar type from x
Eigen::Array4d result = ind_vec.unaryExpr(x);

std::cout << "result^T = " << result.transpose() << std::endl;

// Output:
// result^T = 1.1 3.3 5.5 6.6
Run Code Online (Sandbox Code Playgroud)

唯一需要注意的是,这至少需要 C++11 才能工作。问题是 eigen 内部依赖于std::result_of获取标量结果类型。否则,您可能会收到错误,指出需要强制转换。


Pet*_*erT 5

如果仅用于向量,似乎很容易编写自己:

#include "Eigen/Core"

template <typename T, typename T2>
T extract(const T2& full, const T& ind)
{
    int num_indices = ind.innerSize();
    T target(num_indices);
    for (int i = 0; i < num_indices; i++)
    {
        target[i] = full[ind[i]];
    }
    return target;
}

int main()
{
    Eigen::VectorXd full(8); 
    full << 1, 2, 3, 4, 5, 6, 7, 8;
    Eigen::Vector4d ind_vec(4);
    ind_vec << 0, 2, 4, 5;
    std::cout << "full:" << full<< std::endl;
    std::cout << "ind_vec:" << ind_vec<< std::endl;
    std::cout << "extracted" << extract(full,ind_vec) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这应该适用于大多数情况

编辑:对于索引标量类型与源和目标标量类型不同的情况,以下将起作用(对于所有内置特征类型)。

template <typename T, typename T2>
Eigen::Matrix<typename T2::Scalar,T::RowsAtCompileTime,T::ColsAtCompileTime,T::Options> 
extract2(const Eigen::DenseBase<T2>& full, const Eigen::DenseBase<T>& ind)
{
    using target_t = Eigen::Matrix < T2::Scalar, T::RowsAtCompileTime, T::ColsAtCompileTime, T::Options > ;
    int num_indices = ind.innerSize();
    target_t target(num_indices);
    for (int i = 0; i < num_indices; i++)
    {
        target[i] = full[ind[i]];
    }
    return target;
} 
Run Code Online (Sandbox Code Playgroud)

(这与另一个不同,因为您可以使用整数向量作为索引,使用双精度向量作为源,并返回双精度向量而不是extract()上面的整数向量)


小智 5

现在 Eigen 3.4 通过切片和索引支持这一点:

Eigen::VectorXd x(8); x<<1,2,3,4,5,6,7,8;
Eigen::VectorXi ind_vec(4); ind_vec<<0,2,4,5;

Eigen::VectorXd x_slice = x(ind_vec);
Run Code Online (Sandbox Code Playgroud)

正如文档所指出的,ind_vec也可以

存储为 ArrayXi、std::vector、std::array<int,N> 等的行或列索引的任意列表。