获取由向量向量表示的矩阵的第一列

时间:2013-04-03 03:30:28

标签: c++ vector matrix transpose indices

假设我使用foo表示值的矩阵std::vector

int rows = 5;
int cols = 10;    
auto foo = vector<vector<double>>(rows, vector<double>(cols));

我是否有一种非常简单的方法可以获得包含foo第一个“列”的vector<int>大小rows

{foo[0][0], foo[0][1], foo[0][2], foo[0][3], foo[0][4] }

换句话说,我可以“转置”foo,以便以下三件事情成立:

foo_transpose.size() == cols
foo_transpose[0].size() == rows
foo_transpose[0] == {foo[0][0], foo[0][1], foo[0][2], foo[0][3], foo[0][4] }

澄清说明

对于表示“矩阵”的替代方法,有一些很好的建议。当我使用术语“矩阵”时,我只是意味着每个第二级vector的大小都相同。我并不是说我将使用这种数据结构进行线性代数类型操作。我实际上需要一个向量矢量,或者一个数据结构,你可以从中“拉出”1D向量,因为我有像以下向量一样运行的函数:

double sum(vector<double> const & v);

我打电话给:

sum(foo[0]);

在一个特殊情况下,我遇到了一个需要做的事情:

sum({foo[0][0], foo[0][1], foo[0][2], foo[0][3], foo[0][4] };

For Loop Solution

有一个明显的f​​or循环解决方案,但我一直在寻找更强大和更有效的东西。

1 个答案:

答案 0 :(得分:19)

正如我在评论中提到的,出于以下几个原因,使用向量矢量表示矩阵是不切实际的:

  1. 设置很繁琐;
  2. 很难改变;
  3. 缓存位置不好。
  4. 这是我创建的一个非常简单的类,它将在单个向量中保存2D矩阵。这就像MATLAB这样的软件如何做到这一点......虽然是一个很大的简化。

    template <class T>
    class SimpleMatrix
    {
    public:
        SimpleMatrix( int rows, int cols, const T& initVal = T() );
    
        // Size and structure
        int NumRows() const                       { return m_rows; }
        int NumColumns() const                    { return m_cols; }
        int NumElements() const                   { return m_data.size(); }
    
        // Direct vector access and indexing
        operator const vector<T>& () const        { return m_data; }
        int Index( int row, int col ) const       { return row * m_cols + col; }
    
        // Get a single value
              T & Value( int row, int col )       { return m_data[Index(row,col)]; }
        const T & Value( int row, int col ) const { return m_data[Index(row,col)]; }
              T & operator[]( size_t idx )        { return m_data[idx]; }
        const T & operator[]( size_t idx ) const  { return m_data[idx]; }
    
        // Simple row or column slices
        vector<T> Row( int row, int colBegin = 0, int colEnd = -1 ) const;
        vector<T> Column( int row, int colBegin = 0, int colEnd = -1 ) const;
    
    private:
        vector<T> StridedSlice( int start, int length, int stride ) const;
    
        int m_rows;
        int m_cols;
    
        vector<T> m_data;
    };
    

    这个课程基本上是围绕单一功能涂糖 - StridedSlice。其实施是:

    template <class T>
    vector<T> SimpleMatrix<T>::StridedSlice( int start, int length, int stride ) const
    {
        vector<T> result;
        result.reserve( length );
        const T *pos = &m_data[start];
        for( int i = 0; i < length; i++ ) {
            result.push_back(*pos);
            pos += stride;
        }
        return result;
    }
    

    其余的很简单:

    template <class T>
    SimpleMatrix<T>::SimpleMatrix( int rows, int cols, const T& initVal )
        : m_data( rows * cols, initVal )
        , m_rows( rows )
        , m_cols( cols )
    {    
    }
    
    template <class T>
    vector<T> SimpleMatrix<T>::Row( int row, int colBegin, int colEnd ) const
    {
        if( colEnd < 0 ) colEnd = m_cols-1;
        if( colBegin <= colEnd )
            return StridedSlice( Index(row,colBegin), colEnd-colBegin+1, 1 );
        else
            return StridedSlice( Index(row,colBegin), colBegin-colEnd+1, -1 );
    }
    
    template <class T>
    vector<T> SimpleMatrix<T>::Column( int col, int rowBegin, int rowEnd ) const
    {
        if( rowEnd < 0 ) rowEnd = m_rows-1;
        if( rowBegin <= rowEnd )
            return StridedSlice( Index(rowBegin,col), rowEnd-rowBegin+1, m_cols );
        else
            return StridedSlice( Index(rowBegin,col), rowBegin-rowEnd+1, -m_cols );
    }
    

    请注意,RowColumn函数的设置方式使您可以轻松请求整行或列,但功能更强大,因为您可以通过传递来切片范围一个或两个以上的参数。是的,您可以通过使起始值大于结束值来反向返回行/列。

    这些功能中没有内置边界检查,但您可以轻松添加。

    您还可以添加一些内容以将区域切片作为另一个SimpleMatrix<T>返回。

    玩得开心。