我的{strong>变量数量为std::vectors<int>
,假设我在此示例中有3个向量:
std::vector<int> vect1 {1,2,3,4,5};
std::vector<int> vect2 {1,2,3,4,5};
std::vector<int> vect3 {1,2,3,4,5};
这里的矢量值并不重要。此外,这些向量的长度也是可变的。
从这些向量中,我想创建向量值的每个排列,所以:
{1, 1, 1}
{1, 1, 2}
{1, 1, 3}
...
...
...
{3, 5, 5}
{4, 5, 5}
{5, 5, 5}
然后,我会将每个组合插入到键值对映射中,以便与我的应用程序一起使用。
实现这一目标的有效方法是什么?我通常只使用for
循环,并遍历所有参数来创建所有组合,但向量的数量是可变的。
谢谢。
编辑:我将包含更多细节。
所以,首先,我并没有真正处理int
,而是一个自定义对象。 int
只是为了简单起见。矢量本身存在于像std::map<std::string, std::vector<int> >
这样的地图中。
我的最终目标是拥有一个std::vector< std::map< std::string, int > >
,它本质上是每个可能的名称 - 值对组合的集合。
答案 0 :(得分:1)
0 - &gt; 0,0,0
1 - &gt; 0,0,1
2 - &gt; 0,1,0
3 - &gt; 0,1,1
4 - &gt; 1,0,0
...
7 - &gt; 1,1,1-
8 - &gt; 1,1,2
...
地图应该将线性整数转换为组合(即:a1,a2,a3 ......组合),允许您从每个向量中选择一个元素来获得答案。
无需复制初始向量中的任何值。您可以使用数学公式为每个向量找到正确的答案。那个公式将取决于输入向量的一些属性(有多少属性?它们的长度是否相同?它们有多长?等等......)
答案 1 :(得分:1)
“我需要生成X的所有排列”形式的许多(也许是大多数)问题可以通过创造性地使用简单计数来解决(这也不例外)。
让我们从简单的例子开始:每个5个元素的3个向量。对于我们的答案,我们将查看这些向量的索引作为3位数的基数为5的数字。该数字的每个数字都是其中一个向量的索引。
因此,为了生成所有组合,我们只需从0到5 3 (125)计数。我们将每个数字转换为3个基数为5的数字,并使用这些数字作为向量的索引来获得排列。当我们达到125时,我们列举了这些向量的所有排列。
假设向量总是相等的长度,改变向量的长度和/或数量只需要改变我们使用的数字和/或数字基数。
如果向量长度不等,我们只生成一个结果,其中并非所有数字都在同一个基数中。例如,给定三个长度分别为7,4和10的向量,我们仍然计算从0到7x4x10 = 280.我们生成最低有效数字为N%10。我们生成下一个最不重要的(N / 10)%4。
据推测,这足以使如何将概念扩展到任意数量的向量,每个都是任意大小。
答案 2 :(得分:0)
这是Lother和Jerry Coffin描述的一个显式实现,使用for
循环中有用的div
函数迭代不同长度的向量。
#include <cstdlib> // ldiv
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
vector<int> vect1 {100,200};
vector<int> vect2 {10,20,30};
vector<int> vect3 {1,2,3,4};
typedef map<string,vector<int> > inputtype;
inputtype input;
vector< map<string,int> > output;
int main()
{
// init vectors
input["vect1"] = vect1;
input["vect2"] = vect2;
input["vect3"] = vect3;
long N = 1; // Total number of combinations
for( inputtype::iterator it = input.begin() ; it != input.end() ; ++it )
N *= it->second.size();
// Loop once for every combination to fill the output map.
for( long i=0 ; i<N ; ++i )
{
ldiv_t d = { i, 0 };
output.emplace_back();
for( inputtype::iterator it = input.begin() ; it != input.end() ; ++it )
{
d = ldiv( d.quot, input[it->first].size() );
output.back()[it->first] = input[it->first][d.rem];
}
}
// Sample output
cout << output[0]["vect1"] << endl; // 100
cout << output[0]["vect2"] << endl; // 10
cout << output[0]["vect3"] << endl; // 1
cout << output[N-1]["vect1"] << endl; // 200
cout << output[N-1]["vect2"] << endl; // 30
cout << output[N-1]["vect3"] << endl; // 4
return 0;
}
答案 3 :(得分:0)
使用矢量数组而不是单独的变量。然后使用以下递归算法: -
permutations(i,k,vectors[],choices[]) {
if(i<k) {
for(int x=0;x<vectors[i].size();x++) {
choices[i] = x;
permutations(i+1,k,vectors,choices);
}
}
else {
printf("\n %d",vectors[choices[0]]);
for(int j=1;j<k;j++) {
printf(",%d",vectors[choices[j]]);
}
}
}
答案 4 :(得分:0)
以下可能有所帮助:(https://ideone.com/1Xmc9b)
template <typename T>
bool increase(const std::vector<std::vector<T>>& v, std::vector<std::size_t>& it)
{
for (std::size_t i = 0, size = it.size(); i != size; ++i) {
const std::size_t index = size - 1 - i;
++it[index];
if (it[index] == v[index].size()) {
it[index] = 0;
} else {
return true;
}
}
return false;
}
template <typename T>
void do_job(const std::vector<std::vector<T>>& v, std::vector<std::size_t>& it)
{
// Print example.
for (std::size_t i = 0, size = v.size(); i != size; ++i) {
std::cout << v[i][it[i]] << " ";
}
std::cout << std::endl;
}
template <typename T>
void iterate(const std::vector<std::vector<T>>& v)
{
std::vector<std::size_t> it(v.size(), 0);
do {
do_job(v, it);
} while (increase(v, it));
}