获取由向量的向量表示的矩阵的第一列 [英] Get the first column of a matrix represented by a vector of vectors

查看:46
本文介绍了获取由向量的向量表示的矩阵的第一列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose I'm representing a matrix foo of values using std::vector:

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

是否有一种巧妙简单的方法可以让我获得一个 vector 大小的 rows 包含 foo 的第一个列":

Is there a cleverly simple way for me to get a vector<int> of size rows that contains the first "column" of foo:

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

换句话说,我可以转置"foo 以使以下三件事为真:

Put another way, can I "transpose" foo so that the following three things are true:

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 的大小都相同.我并不是要建议我将这个数据结构用于线性代数类型的运算.我实际上确实需要一个向量向量,或者一个可以从中拉出"一维向量的数据结构,因为我有对向量进行操作的函数,例如:

Clarifying Note

There are a few good suggestions for alternative ways to represent a "matrix". When I use the term "matrix" I simply mean that each of the second level vector's will be the same size. I don't mean to suggest that I will be using this data structure for linear algebra type operation. I actually DO need a vector of vectors, or a data structure from which you can "pull out" 1D vectors, because I have functions that operate on vectors like:

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

我打电话给:

sum(foo[0]);

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

It's just in a special case I came up to a situation that need to do:

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

For 循环解决方案

有一个明显的 for 循环解决方案,但我一直在寻找更健壮和高效的方法.

For Loop Solution

There is an obvious for loop solution, but I was looking for something more robust and efficient.

推荐答案

正如我在评论中提到的,由于以下几个原因,使用 vector-of-vector 表示矩阵是不切实际的:

As I mentioned in the comments, it's not practical to represent matrices using vector-of-vector for a few reasons:

  1. 设置起来很繁琐;
  2. 很难改变;
  3. 缓存位置不好.

这是我创建的一个非常简单的类,它将在单个向量中保存一个 2D 矩阵.这几乎就是 MATLAB 之类的软件的工作方式……尽管进行了极大的简化.

Here is a very simple class I have created that will hold a 2D matrix in a single vector. This is pretty much how software like MATLAB does it... albeit a huge simplification.

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.其实现是:

This class is basically sugar-coating around a single function -- StridedSlice. The implementation of that is:

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 函数的设置方式使您可以轻松请求整行或整列,但功能更强大一些,因为您可以通过传递一个或两个以上的参数来分割一个范围.是的,您可以通过使起始值大于结束值来反向返回行/列.

Note that the Row and Column functions are set up in such a way that you can easily request an entire row or column, but are a little more powerful because you can slice a range by passing one or two more parameters. And yes, you can return the row/column in reverse by making your start value larger than your end value.

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

There is no bounds-checking built into these functions, but you can easily add that.

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

You could also add something to return an area slice as another SimpleMatrix<T>.

玩得开心.

这篇关于获取由向量的向量表示的矩阵的第一列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆