gpt4 book ai didi

c++ - 获取由 vector 的 vector 表示的矩阵的第一列

转载 作者:可可西里 更新时间:2023-11-01 15:41:24 27 4
gpt4 key购买 nike

假设我代表一个矩阵 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 以使以下三件事为真:

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的大小相同。我并不是说我会使用这个数据结构来进行线性代数类型的运算。我实际上确实需要一个 vector 的 vector ,或者一个可以从中“拉出”一维 vector 的数据结构,因为我有对 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] };

For循环解决方案

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

最佳答案

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

  1. 设置起来很繁琐;
  2. 很难改变;
  3. 缓存局部性不好。

这是我创建的一个非常简单的类,它将在单个 vector 中保存一个二维矩阵。这几乎就是像 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 col, int rowBegin = 0, int rowEnd = -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> .

玩得开心。

关于c++ - 获取由 vector 的 vector 表示的矩阵的第一列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15778377/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com