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

时间:2014-10-08 22:01:00

标签: c++ eigen eigen3

假设我有

Eigen::VectorXd x; //{1,2,3,4,5,6,7,8}

Eigen::VectorXd ind_vec; //{0,2,4,5}

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

类似的东西:

x.extract(ind_vec) returning {1, 3, 5, 6}

4 个答案:

答案 0 :(得分:9)

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

#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;
}

将输出:

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

我还没有用矢量测试它,但我想也应该可以。

答案 1 :(得分:4)

似乎它很容易自己写,如果它只是为了矢量:

#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;
}

这适用于大多数情况

编辑:如果您的索引标量类型与源标量和目标标量类型不同,则以下内容将适用(对于所有内置特征类型)。

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;
} 

(这与另一个不同之处在于你可以使用int的矢量作为索引和双精度矢量作为源并获得一个双精度矢量而不是上面的extract()的整数矢量做)

答案 2 :(得分:2)

在C ++ 11(及以上)中执行此操作:

 ind_vec.unaryExpr(x);

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

 Scalar operator() (Index index) const {
     return x[index];
 }

碰巧,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

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

答案 3 :(得分:-1)

使用libigl的igl::slice,您可以通过以下方式实现:

Eigen::VectorXd result;
igl::slice(x,ind_vec,result);