Unfortunately Tom de Geus' answer does not maintain dimensionality and hence transforms the xarray of shape {2, 3}
into a vector of size 6
.
I stepped over this question, when attempting to construct a nested vector in order to plot a xarray
with matplotlibcpp
. For me it turned out, that Eigen::Matrix.. is a way more suitable class for this purpose. For the 2 dimensional case, one can comfortable convert the Eigen::Matrix to a nested std::vector. For higher dimensions, its worth to have a look here.
Code
transforms xt::xarray
to Eigen::MatrixXf
to nested std::vector
#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"
#include <Eigen/Dense>
//https://mcmap.net/q/274021/-convert-eigen-matrix-to-c-array
Eigen::MatrixXf xarray_to_matrixXf(xt::xarray<float> arr)
{
auto shape = arr.shape();
int nrows = shape[0];
int ncols = shape[1];
Eigen::MatrixXf mat = Eigen::Map<Eigen::MatrixXf>(arr.data(), nrows, ncols);
return mat;
}
// https://mcmap.net/q/1621810/-converting-eigen-matrixxf-to-2d-std-vector
std::vector<std::vector<float>> matrixXf2d_to_vector(Eigen::MatrixXf mat)
{
std::vector<std::vector<float>> vec;
for (int i=0; i<mat.rows(); ++i)
{
const float* begin = &mat.row(i).data()[0];
vec.push_back(std::vector<float>(begin, begin+mat.cols()));
}
return vec;
}
// print a vector
// https://mcmap.net/q/1621811/-pretty-printing-nested-vectors
template<typename T1>
std::ostream& operator <<( std::ostream& out, const std::vector<T1>& object )
{
out << "[";
if ( !object.empty() )
{
for(typename std::vector<T1>::const_iterator
iter = object.begin();
iter != --object.end();
++iter) {
out << *iter << ", ";
}
out << *--object.end();
}
out << "]";
return out;
}
int main()
{
xt::xarray<float> xArr {{nan(""), 9}, {5, -6}, {1, 77}};
std::cout << "xt::xarray<float> xArr = \n" << xArr << std::endl;
Eigen::MatrixXf eigMat = xarray_to_matrixXf(xArr);
std::cout << "Eigen::MatrixXf eigMat = \n" << eigMat << std::endl;
std::vector<std::vector<float>> vec = matrixXf2d_to_vector(eigMat);
std::cout << "std::vector<std::vector<float>> vec = " << vec << std::endl;
return 0;
}
Output
xt::xarray<float> xArr =
{{nan., 9.},
{ 5., -6.},
{ 1., 77.}}
Eigen::MatrixXf eigMat =
nan -6
9 1
5 77
std::vector<std::vector<float>> vec = [[nan, 9], [9, 5], [5, -6]]