2013-07-16 20 views
0

以下是我的代碼,用於將形狀[3 4 2]的boost :: multi_array重塑爲[12 2]。由於尺寸固定在boost :: multi_array中,因此我首先將三維陣列重塑爲形狀[12 2 1],然後將前兩個尺寸複製到新陣列中。我可以在不復制其內容的情況下移除boost :: multi_array的單個維度嗎?

是否有一個更簡單的方法,不會做任何複製(我寧願只是在numpy.reshape的精神的原始數據視圖)。

g++ -g test.cc && ./a.out

#include "boost/multi_array.hpp"                                                                       
#include <cassert>                                                                           
#include <iostream>                                                                           


int                                                                               
main() {                                                                             
    // Create a 3D array that is 3 x 4 x 2                                                                     
    typedef boost::multi_array<double, 3> array_type;                                                                   
    typedef array_type::index index;                                                                       

    array_type A(boost::extents[3][4][2]);                                                                     

    // indexer can be const a boost::array                                                                     
    boost::array<array_type::index,3> idx = {{0,0,0}};                                                                  

    // Assign values to the elements                                                                       
    int values = 0;                                                                           
    for(index i = 0; i != 3; ++i)                                                                        
    for(index j = 0; j != 4; ++j)                                                                       
     for(index k = 0; k != 2; ++k)                                                                       
     A[i][j][k] = values++;                                                                        
    std::cout << "array elements: " << A.num_elements() << std::endl;                                                               
    std::cout << "array ndim: " << A.num_dimensions() << std::endl;                                                               
    std::cout << "array size: " << A.size() << std::endl; // equivalent to a.shape()[0];                                                          
    std::cout << "array shape: " << A.shape()[0] <<" " << A.shape()[1] <<" " << A.shape()[2] << std::endl;                                                     

    int verify = 0;                                                                           
    for(index i = 0; i != 3; ++i)                                                                        
    for(index j = 0; j != 4; ++j)                                                                       
     for(index k = 0; k != 2; ++k) {                                                                      
     std::cout << "A[" <<i <<"]["<<j<<"]["<<k<<"] = " << A[i][j][k] << std::endl;                                                          
     assert(A[i][j][k] == verify++);                                                                      
     }                                                                              

    boost::array<array_type::index,3> dims2 = {{12, 2, 1}};                                                                 
    A.reshape(dims2);                                                                           

    std::cout << "array shape: " << A.shape()[0] <<" " << A.shape()[1] <<" " << A.shape()[2] << std::endl;                                                     
    for(index i = 0; i != 12; ++i)                                                                       
    for(index j = 0; j != 2; ++j)                                                                       
     for(index k = 0; k != 1; ++k) {                                                                      
     std::cout << "A[" <<i <<"]["<<j<<"]["<<k<<"] = " << A[i][j][k] << std::endl;                                                          
     }                                                                              

    typedef boost::multi_array<double, 2> Array2d;                                                                   
    Array2d B(boost::extents[12][2]);                                                                       
    for(index i = 0; i != 12; ++i)                                                                       
    for(index j = 0; j != 2; ++j){                                                                       
     B[i][j] = A[i][j][0];                                                                         
     std::cout << "B[" <<i <<"]["<<j<<"] = " << B[i][j] << std::endl;                                                              
    }                                                                              
    return 0;                                                                             
} 

回答

1

我不認爲你可以做的是,在一般的情況下。你可以做的是產生一個低維的子視圖。我讀了你的代碼,你想讓你的二維數組與原始3D數組一樣多。

你可以做什麼是const_multi_array_ref重用3D陣列的現有數據:

boost::multi_array< int, 3 > a(boost::extents[ 2 ][ 3 ][ 4 ]); 
boost::const_multi_array_ref< int, 2 > b(a.data(), boost::extents[ 2 ][ 12 ]); 

根據存儲順序,這可能做你的努力將收購上。

我會建議圍繞一個multi_array寫一個小包裝,它使用所需的索引計算來訪問multi_array

+0

感謝您的回答。這絕對比我的解決方案好。這個修改後的行做我想要的:'boost :: const_multi_array_ref < double, 2 > B(A.data(),boost :: extents [12] [2]);' – Sebastian

+0

如果我正確理解'multi_array :: reshape'的作用,效果與我的方法類似(我仍然會考慮爲可讀性和靈活性編寫小封裝)。如果我的答案似乎可以接受,請接受它。 – mkluwe

1

運行原來,這是通過使用查看(C.F. Creating Views)成爲可能。

在我的例子:

... reshape ... 

typedef boost::multi_array_types::index_range range;                  
array_type::index_gen indices; 
array_type::array_view<2>::type myview =  
    A[ indices[range(0,12)][range(0,2)][0] ];         
for(index i = 0; i != 12; ++i)  
    for(index j = 0; j != 2; ++j){ 
    std::cout << "myview[" <<i <<"]["<<j<<"] = " << myview[i][j] << std::endl; 
相關問題