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

Ala*_*ing 11 c++ transpose vector matrix indices

假设我foo使用std::vector以下方法表示值矩阵:

int rows = 5;
int cols = 10;    
auto foo = vector<vector<double>>(rows, vector<double>(cols));
Run Code Online (Sandbox Code Playgroud)

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

{foo[0][0], foo[0][1], foo[0][2], foo[0][3], foo[0][4] }
Run Code Online (Sandbox Code Playgroud)

换句话说,我可以"转置"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] }
Run Code Online (Sandbox Code Playgroud)

澄清说明

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

double sum(vector<double> const & v);
Run Code Online (Sandbox Code Playgroud)

我打电话给:

sum(foo[0]);
Run Code Online (Sandbox Code Playgroud)

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

sum({foo[0][0], foo[0][1], foo[0][2], foo[0][3], foo[0][4] };
Run Code Online (Sandbox Code Playgroud)

对于Loop Solution

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

pad*_*ddy 19

正如我在评论中提到的那样,使用向量矢量来表示矩阵是不切实际的,原因如下:

  1. 建立起来很繁琐;
  2. 很难改变;
  3. 缓存局部性很差.

这是我创建的一个非常简单的类,它将在单个向量中保存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;
};
Run Code Online (Sandbox Code Playgroud)

这个类基本上是围绕单一功能的糖涂层 - 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;
}
Run Code Online (Sandbox Code Playgroud)

剩下的就是直截了当:

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 );
}
Run Code Online (Sandbox Code Playgroud)

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

这些函数没有构建边界检查,但您可以轻松添加它.

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

玩得开心.

  • 我应该明确声明这是一个行主要表示.我模糊地将它与MATLAB进行了比较,我应该提到它是专栏.使用最适合您的访问需求的表示. (2认同)
  • 是的,设置透明方法以返回切片作为参考将很棘手。也许可以用valarray来实现。对于const和非const方法,可以在其中分配给特定值,但如果仅从容器的const版本读取值,则还可以保持const正确性。 (2认同)