得到的矩阵的第一列由向量的向量表示(Get the first column of a matrix

2019-08-19 03:56发布

假如我是代表一个矩阵foo使用值std::vector

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

有我得到一个巧妙的简单方法vector<int>大小rows包含foo的第一个“列”:

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

换句话说,我可以“转”富为将以下三项条件:

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的将是相同的大小。 我的意思不是暗示我将利用这个数据结构,线性代数型操作。 其实我需要载体的载体,或数据结构,从中可以“拔出”维向量,因为我有像载体操作功能:

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

对于循环解决方案

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

Answer 1:

正如我在评论中所提到的,它不是实际使用矢量的矢量,有几个原因来表示矩阵:

  1. 这是繁琐的设置;
  2. 这是难以改变;
  3. 缓存位置是坏的。

这里是一个非常简单的类我创建了将在一个向量持有一个二维矩阵。 这很像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>

玩得开心。



文章来源: Get the first column of a matrix represented by a vector of vectors