想象一下包含以下元素的3行3列矩阵:
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
我想编写一个函数来提取triples的每个组合,其中第一个元素来自column1,第二个元素来自第2列等。第一个这样的三元组可能是
1,4,7, then
1,4,8
1,4,9
1,5,7
1,5,8 and so on
每个三元组应该是另一个函数的参数。在该示例中,通常存在27个这样的三元组,行^列。
虽然对于这个例子,我可以编写3个嵌套for循环迭代三列,我想有一个函数可以处理任何n行和m列的矩阵。
在R中,有expand.grid
函数可用于此但我希望有一个简单的C ++解决方案(不调用Rcpp)。
如果我有:
std::vector<double> col1 = {1,2,3};
std::vector<double> col2 = {4,5,6};
std::vector<double> col3 = {7,8,9};
std::vector<std::vector<double>> matrix = {col1,col2,col3};
std::vector<std::vector<double>> result = generateGrid(matrix);
// result should contain [[1,4,7], [1,4,8], etc];
答案 0 :(得分:1)
如果我做对了,你的问题就像打印所有n元组一样,其中每个元素都在[0,m]中,然后它将成为m,n矩阵的索引。这可以通过递归轻松完成:
使用范围[0,m)中的元素打印所有n元组:
for each number from [0,m):
1. print number
2. print all (n-1)-tuples with elements from range [0,m)
可以将其翻译成以下代码:
#include <vector>
#include <iostream>
using row_t = std::vector<double>;
using matrix_t = std::vector<row_t>;
void function_impl(size_t col, size_t row, const size_t numCols, const size_t numRows, row_t& rBuff, const matrix_t& m, matrix_t& result)
{
rBuff[col] = m[row][col];
if (col == numCols - 1)//If we've filled the permutation, append it to result
result.push_back(rBuff);
else//Fill rest of row with all possible combinations
{
for (size_t r = 0; r < numRows; ++r)
function_impl(col + 1, r, numCols, numRows, rBuff, m, result);
}
}
matrix_t function(const matrix_t& m)
{
size_t numRows = m[0].size();//Assumes rectangular matrix
size_t numCols = m.size();
matrix_t result;
row_t rowBuffer(numCols);//Buffer to store current permutation of indices
//Places all possible indices into first element of permutation and recurses
for (size_t r = 0; r < numRows; ++r)
function_impl(0, r, numCols, numRows, rowBuffer, m, result);
return result;
}
int main()
{
row_t col1 = {1,2,3};
row_t col2 = {4,5,6};
row_t col3 = {7,8,9};
matrix_t matrix = {col1,col2,col3};
//Prints all 27 combinations
for (const auto& row : function(matrix))
{
for (const auto& el : row)
std::cout << el << " ";
std::cout << '\n';
}
system("PAUSE");
}
它确实使用递归到具有常量一行内存的列数的深度。当然,生成的矩阵将包含m ^ n个元素,但是如果您只需要打印它们,您可以立即执行此操作,而不是追加到结果并一起删除结果矩阵。
答案 1 :(得分:0)
#include <iostream>
#include <vector>
using namespace std;
using matrix_t = vector < vector < double > >
//class for simulating multiple for(int i=from ;i<=to;++i) in a row
class multi_iterator
{
using Iterators = size_t*;
private:
Iterators iterators; //array of iterators for multiple synchronized but different iterations
//through the same interval from-to
size_t iter_amount; //number of iterators in array above
//all are iterating from - to
size_t from;
size_t to;
public:
multi_iterator(size_t number_of_iterators , size_t _from , size_t _to)
{
iter_amount = number_of_iterators;
iterators = new size_t[number_of_iterators]();
from = _from;
to = _to;
}
int get_value(size_t iterator_id)// iter_id is the index of an iterator inside array iterators
{
return iterators[iterator_id];
}
int end()//if the last iterator is greater than "to" the iterations are over and the function returns true
{
if( iterators[iter_amount-1] >to )
return true;
else return false;
}
//increments in a synchronized order
void operator++()
{
int iter_id = 0;
while(iter_id < iter_amount) //start the loop with the first iterator
{
if(iterators[iter_id] < to) //if the iterator didnt reach the upper boundary "to"
{
++iterators[iter_id]; //increment the iterator
break;
}
else if( iterators[iter_id] == to ) //if the iterator reached the upper boundery "to"
{
if( iter_id < iter_amount-1 ) //if it's not the last iterator
{
iterators[iter_id]=0; //turn the iterator back to 0
++iter_id; //move on to the next iterator
continue; //continue the loop with the next iterator
}
else //the last iterator reached the upper boundery
{
++iterators[iter_id]; // the iterations are over
break;
}
}
}
}
};
void function(const matrix_t& matrix)
{
size_t columns = matrix.size();
if(columns > 0 )
{
size_t rows = matrix[0].size();
multi_iterator it(columns , 0 , rows-1 );//we need a row-iterator(from 0 to "row") for every column
while( !it.end() )
{
for(size_t i=0;i < columns;++i)
{
size_t iter_value_column_i = it.get_value(i);
cout<< matrix[i][ iter_value_column_i ]<<" ";
}
cout<<endl;
++it;
}
}
}
int main()
{
std::vector<double> col1 = {1,2};
std::vector<double> col2 = {4,5};
std::vector<double> col3 = {7,8};
std::vector<std::vector<double>> matrix = {col1,col2,col3};
function(matrix);
return 0;
}