C++中多重vector的遍历

LL596214569 2019-01-11 03:10:41
别人发给我的一个里面装着vector的vector,像下面这样使用,有没有什么更简洁更有效一点的写法,求大佬

vector<vector<float> > vParam;
vector<float>::iterator itera, iterb, iterc, iterd, itere, iterf, iterg, iterh, iteri, iterj;
for (itera = vParam[0].begin(); itera != vParam[0].end(); itera++)
for (iterb = vParam[1].begin(); iterb != vParam[1].end(); iterb++)
for (iterc = vParam[2].begin(); iterc != vParam[2].end(); iterc++)
for (iterd = vParam[3].begin(); iterd != vParam[3].end(); iterd++)
for (itere = vParam[4].begin(); itere != vParam[4].end(); itere++)
for (iterf = vParam[5].begin(); iterf != vParam[5].end(); iterf++)
for (iterg = vParam[6].begin(); iterg != vParam[6].end(); iterg++)
for (iterh = vParam[7].begin(); iterh != vParam[7].end(); iterh++)
for (iteri = vParam[8].begin(); iteri != vParam[8].end(); iteri++)
for (iterj = vParam[9].begin(); iterj != vParam[9].end(); iterj++)
{
float fParams[10] = {0.0f};
if (nParamNum > 0)
{
fParams[0] = *itera;
}
if (nParamNum > 1)
{
fParams[1] = *iterb;
}
if (nParamNum > 2)
{
fParams[2] = *iterc;
}
if (nParamNum > 3)
{
fParams[3] = *iterd;
}
if (nParamNum > 4)
{
fParams[4] = *itere;
}
if (nParamNum > 5)
{
fParams[5] = *iterf;
}
if (nParamNum > 6)
{
fParams[6] = *iterg;
}
if (nParamNum > 7)
{
fParams[7] = *iterh;
}
if (nParamNum > 8)
{
fParams[8] = *iteri;
}
if (nParamNum > 9)
{
fParams[9] = *iterj;
}

//处理fParms
if(fParams)
{....}

}
...全文
1260 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
aaasssdddd96 2019-10-19
  • 打赏
  • 举报
回复
有的

float fParams[10];
vector<float>::iterator iter[10];
int i;

for(i=0; i<10 && i<nParaNum; i++) {
for(iter[i]=vParam[i].begin(),itera != vParam[i].end(); iter[i]++) {
fParams[i] = *iter[i];
goto inc_i;
next: ;
}
goto dec_i;

inc_i: ;
}
//处理fParms
if(fParams)
{....}

dec_i;:
--i;
if (i>=0) goto next;
LL596214569 2019-01-15
  • 打赏
  • 举报
回复
引用 17 楼 srhouyu 的回复:
[quote=引用 2 楼 LL596214569 的回复:]
总体上来说,如果组合数非常多,那么方法二比方法一效率高,而且方法二没有unsigned long大小的限制。[/quote] 好的 谢谢
srhouyu 2019-01-13
  • 打赏
  • 举报
回复
引用 11 楼 LL596214569 的回复:
[quote=引用 10 楼 srhouyu 的回复:] 你知不知道这段代码这么诡异,到底是干啥用的? 如果这个二维vector是m列n行的,那这么多重循环,对矩阵每行中任取一个元素进行完排列,一共会循环m^n次。这一定是在做什么非比寻常的事情。你要是不清楚它在干啥,我们就更不清楚了。 不知道它在干啥,还是别改为妙。 你的首要工作就是去问那个人他脑子里究竟是怎么想的。
这段代码就是为了取到所有vector中数据的组合,之后对这些组合进行一系列操作;现在我想优化的是这里对数据排列的代码,为什么要知道后续他们干了什么? 另外写这段代码的人早就离职了。。。。[/quote] 当然,我有可能把m和n理解反了,不过这不影响。总之第一个维度和第二个维度里面,有一个是进制,另一个就是数位。
LL596214569 2019-01-13
  • 打赏
  • 举报
回复
引用 12 楼 srhouyu 的回复:
[quote=引用 11 楼 LL596214569 的回复:]
[quote=引用 10 楼 srhouyu 的回复:]
你知不知道这段代码这么诡异,到底是干啥用的?
如果这个二维vector是m列n行的,那这么多重循环,对矩阵每行中任取一个元素进行完排列,一共会循环m^n次。这一定是在做什么非比寻常的事情。你要是不清楚它在干啥,我们就更不清楚了。
不知道它在干啥,还是别改为妙。
你的首要工作就是去问那个人他脑子里究竟是怎么想的。

这段代码就是为了取到所有vector中数据的组合,之后对这些组合进行一系列操作;现在我想优化的是这里对数据排列的代码,为什么要知道后续他们干了什么?
另外写这段代码的人早就离职了。。。。[/quote]

如果他的代码没有出现BUG,仅仅是碍眼,那我的建议还是不要去动。俗话说得好,祖传代码就是屎山,已经离职者的代码那就更不用说了。
如果仍然沿着“要全部组合”的思路,那怎么改都还是O(m^n)。这效率不会有本质上的改进。如果你执意要改得好看一些,那么你可以如此考虑:
你的例子里面,m=10,n不定。举个例子n=11,那么所有下标的组合写在一起,就是所有的11位十进制数00000000000~99999999999,共10^11种情况。所以只需要单层循环,i从0循环到99999999999,对于每个i提取其所有十进制数位就是一种组合。
如果m不是10,那就是其他进制的整数,对于每个i提取其所有m进制的数位就行。总之原理一样。注意一下64位整数最大只能到18446744073709551616,别的就没什么了。[/quote]
问题是单个vector里的数据未必是等差的,没法单纯的递加循环啊。。。比如vParam里只有两个vector,第一个vector里面装的是{1,10},第二个vector里面装的是{2,80};我要得到的结果应该是{(1,2),(1,80),(10,2)(10,80)},不是看成位数只有一位那样的。。。
这段代码确实没啥bug,就只是看着很碍眼,也不是非改不可,就是上来问问如果能优化更好。。没什么优化的办法也不是一定要强求改它。
srhouyu 2019-01-13
  • 打赏
  • 举报
回复
引用 2 楼 LL596214569 的回复:
总体上来说,如果组合数非常多,那么方法二比方法一效率高,而且方法二没有unsigned long大小的限制。
srhouyu 2019-01-13
  • 打赏
  • 举报
回复
引用 14 楼 LL596214569 的回复:
[quote=引用 12 楼 srhouyu 的回复:] [quote=引用 11 楼 LL596214569 的回复:] [quote=引用 10 楼 srhouyu 的回复:] 你知不知道这段代码这么诡异,到底是干啥用的? 如果这个二维vector是m列n行的,那这么多重循环,对矩阵每行中任取一个元素进行完排列,一共会循环m^n次。这一定是在做什么非比寻常的事情。你要是不清楚它在干啥,我们就更不清楚了。 不知道它在干啥,还是别改为妙。 你的首要工作就是去问那个人他脑子里究竟是怎么想的。
这段代码就是为了取到所有vector中数据的组合,之后对这些组合进行一系列操作;现在我想优化的是这里对数据排列的代码,为什么要知道后续他们干了什么? 另外写这段代码的人早就离职了。。。。[/quote] 如果他的代码没有出现BUG,仅仅是碍眼,那我的建议还是不要去动。俗话说得好,祖传代码就是屎山,已经离职者的代码那就更不用说了。 如果仍然沿着“要全部组合”的思路,那怎么改都还是O(m^n)。这效率不会有本质上的改进。如果你执意要改得好看一些,那么你可以如此考虑: 你的例子里面,m=10,n不定。举个例子n=11,那么所有下标的组合写在一起,就是所有的11位十进制数00000000000~99999999999,共10^11种情况。所以只需要单层循环,i从0循环到99999999999,对于每个i提取其所有十进制数位就是一种组合。 如果m不是10,那就是其他进制的整数,对于每个i提取其所有m进制的数位就行。总之原理一样。注意一下64位整数最大只能到18446744073709551616,别的就没什么了。[/quote] 问题是单个vector里的数据未必是等差的,没法单纯的递加循环啊。。。比如vParam里只有两个vector,第一个vector里面装的是{1,10},第二个vector里面装的是{2,80};我要得到的结果应该是{(1,2),(1,80),(10,2)(10,80)},不是看成位数只有一位那样的。。。 这段代码确实没啥bug,就只是看着很碍眼,也不是非改不可,就是上来问问如果能优化更好。。没什么优化的办法也不是一定要强求改它。[/quote] 给你写了一个

#include<vector>
#include<iostream>
#include<functional>
using namespace std;

typedef unsigned int uint;
typedef unsigned long ulong;

void Method1(vector<vector<float>> vParam, vector<unsigned int> bases);
void Method2(vector< vector<float>> vParam, vector<unsigned int> bases);

int main() {
	vector<vector<float>> vParam = {
		{ 0, 10, 20, 30 },
		{ 100, 110 },
		{ 200, 210, 220, 230, 240 }
	};

	// 统计各位的进制
	vector<uint> bases;	
	cout << "各位的进制:";
	for (auto fvec : vParam) {
		bases.push_back(fvec.size());
		cout << fvec.size() << " ";
	}
	cout << endl << endl;

	// 方法一
	Method1(vParam, bases);

	// 方法二
	Method2(vParam, bases);

	system("pause");
	return 0;
}

void Method1(vector<vector<float>> vParam, vector<uint> bases) {
	uint nDigits = bases.size();
	// 所有样本数,别超ulong范围就行
	ulong nSamples = 1;
	for (uint id = 0; id < nDigits; id++)
		nSamples *= bases[id];
	vector<uint> indices(nDigits, 0);
	cout << "方法一" << endl;
	for (ulong is = 0; is < nSamples; is++) {
		auto sample = is;
		// 提取sample中每个数位
		for (uint id = 0; id < nDigits; id++) {
			// 获得最低位即为一个下标
			uint digit = sample % bases[id];
			// 去掉最低位
			sample /= bases[id];
			// 下标放在列表中
			indices[id] = digit;
		}
		// 打印该组合
		for (uint id = 0; id < nDigits; id++)
			cout << indices[id] << "\t";
		cout << "\t";
		for (uint id = 0; id < nDigits; id++)
			cout << vParam[id][indices[id]] << "\t";
		cout << endl;
	}
	cout << "共有" << nSamples << "种组合" << endl << endl;
}

void Method2(vector<vector<float>> vParam, vector<uint> bases) {
	uint nDigits = bases.size();
	vector<uint> indices(nDigits, 0);
	cout << "方法二" << endl;
	// IncDigit()用来给变进制数indices的任意数位加1
	// 未加满时返回true,加满后返回false
	function<bool(int)> IncDigit;
	IncDigit = [&](int idigit) {
		if (idigit >= nDigits)
			return false;	// 加满了

		if (indices[idigit] + 1 >= bases[idigit]) {
			// 进位
			indices[idigit] = 0;
			return IncDigit(idigit + 1);
		}
		else {
			// 不进位
			indices[idigit] ++;
		}
		return true;
	};

	ulong counter = 0; // 如果counter会超出ulong范围,就不要计数了
	do {
		counter++;
		// 打印该组合
		for (uint id = 0; id < nDigits; id++)
			cout << indices[id] << "\t";
		cout << "\t";
		for (uint id = 0; id < nDigits; id++)
			cout << vParam[id][indices[id]] << "\t";
		cout << endl;
	} while (IncDigit(0)); 	// 在整数的最低位不停+1就得到所有组合了

	cout << "共有" << counter << "种组合" << endl << endl;
}

srhouyu 2019-01-13
  • 打赏
  • 举报
回复
引用 14 楼 LL596214569 的回复:
[quote=引用 12 楼 srhouyu 的回复:] [quote=引用 11 楼 LL596214569 的回复:] [quote=引用 10 楼 srhouyu 的回复:] 你知不知道这段代码这么诡异,到底是干啥用的? 如果这个二维vector是m列n行的,那这么多重循环,对矩阵每行中任取一个元素进行完排列,一共会循环m^n次。这一定是在做什么非比寻常的事情。你要是不清楚它在干啥,我们就更不清楚了。 不知道它在干啥,还是别改为妙。 你的首要工作就是去问那个人他脑子里究竟是怎么想的。
这段代码就是为了取到所有vector中数据的组合,之后对这些组合进行一系列操作;现在我想优化的是这里对数据排列的代码,为什么要知道后续他们干了什么? 另外写这段代码的人早就离职了。。。。[/quote] 如果他的代码没有出现BUG,仅仅是碍眼,那我的建议还是不要去动。俗话说得好,祖传代码就是屎山,已经离职者的代码那就更不用说了。 如果仍然沿着“要全部组合”的思路,那怎么改都还是O(m^n)。这效率不会有本质上的改进。如果你执意要改得好看一些,那么你可以如此考虑: 你的例子里面,m=10,n不定。举个例子n=11,那么所有下标的组合写在一起,就是所有的11位十进制数00000000000~99999999999,共10^11种情况。所以只需要单层循环,i从0循环到99999999999,对于每个i提取其所有十进制数位就是一种组合。 如果m不是10,那就是其他进制的整数,对于每个i提取其所有m进制的数位就行。总之原理一样。注意一下64位整数最大只能到18446744073709551616,别的就没什么了。[/quote] 问题是单个vector里的数据未必是等差的,没法单纯的递加循环啊。。。比如vParam里只有两个vector,第一个vector里面装的是{1,10},第二个vector里面装的是{2,80};我要得到的结果应该是{(1,2),(1,80),(10,2)(10,80)},不是看成位数只有一位那样的。。。 这段代码确实没啥bug,就只是看着很碍眼,也不是非改不可,就是上来问问如果能优化更好。。没什么优化的办法也不是一定要强求改它。[/quote] 触类旁通一下嘛。要是这是个锯齿形二维数组,那就用变进制的大整数,每一位的进制不同就行了。 有两类方法,一是从0循环到最后,对于每个案例然后提取它的每一个数位(每个数位进制都不同)。它在循环时消耗很少,但提取各数位运算一下。而且写起来最简单。 二是写一个简单的变进制整数类,对它不断加1直到足够多,可以无需提取地自然得到每个数位。好处是不需要额外的运算量,缺点是需要多写一个类——当然,这个类得用途狭窄,可以不用那么正经地写出来,用C语言式的数据和方法分开的写法也可以。
srhouyu 2019-01-12
  • 打赏
  • 举报
回复
引用 11 楼 LL596214569 的回复:
[quote=引用 10 楼 srhouyu 的回复:] 你知不知道这段代码这么诡异,到底是干啥用的? 如果这个二维vector是m列n行的,那这么多重循环,对矩阵每行中任取一个元素进行完排列,一共会循环m^n次。这一定是在做什么非比寻常的事情。你要是不清楚它在干啥,我们就更不清楚了。 不知道它在干啥,还是别改为妙。 你的首要工作就是去问那个人他脑子里究竟是怎么想的。
这段代码就是为了取到所有vector中数据的组合,之后对这些组合进行一系列操作;现在我想优化的是这里对数据排列的代码,为什么要知道后续他们干了什么? 另外写这段代码的人早就离职了。。。。[/quote] 如果他的代码没有出现BUG,仅仅是碍眼,那我的建议还是不要去动。俗话说得好,祖传代码就是屎山,已经离职者的代码那就更不用说了。 如果仍然沿着“要全部组合”的思路,那怎么改都还是O(m^n)。这效率不会有本质上的改进。如果你执意要改得好看一些,那么你可以如此考虑: 你的例子里面,m=10,n不定。举个例子n=11,那么所有下标的组合写在一起,就是所有的11位十进制数00000000000~99999999999,共10^11种情况。所以只需要单层循环,i从0循环到99999999999,对于每个i提取其所有十进制数位就是一种组合。 如果m不是10,那就是其他进制的整数,对于每个i提取其所有m进制的数位就行。总之原理一样。注意一下64位整数最大只能到18446744073709551616,别的就没什么了。
LL596214569 2019-01-12
  • 打赏
  • 举报
回复
引用 10 楼 srhouyu 的回复:
你知不知道这段代码这么诡异,到底是干啥用的?
如果这个二维vector是m列n行的,那这么多重循环,对矩阵每行中任取一个元素进行完排列,一共会循环m^n次。这一定是在做什么非比寻常的事情。你要是不清楚它在干啥,我们就更不清楚了。
不知道它在干啥,还是别改为妙。
你的首要工作就是去问那个人他脑子里究竟是怎么想的。

这段代码就是为了取到所有vector中数据的组合,之后对这些组合进行一系列操作;现在我想优化的是这里对数据排列的代码,为什么要知道后续他们干了什么?
另外写这段代码的人早就离职了。。。。
zarelaky 2019-01-12
  • 打赏
  • 举报
回复
引用 6 楼 LL596214569 的回复:
[quote=引用 4 楼 zarelaky 的回复:]
先根据nParamNum判断用哪个vector,再遍历对应的vector计算

nParamNum确定但是最后一个被用到的vector,不是用它来确定用哪个vector。
比如nParamNum = 3,那么用到的是前3个vector不是只用3个vector[/quote]这种东西跟你怎么用vector里面的数据有关系。
总之需要先缩小遍历范围,然后在优化算法,看看能不能降低循环迭代次数。
srhouyu 2019-01-12
  • 打赏
  • 举报
回复
你知不知道这段代码这么诡异,到底是干啥用的? 如果这个二维vector是m列n行的,那这么多重循环,对矩阵每行中任取一个元素进行完排列,一共会循环m^n次。这一定是在做什么非比寻常的事情。你要是不清楚它在干啥,我们就更不清楚了。 不知道它在干啥,还是别改为妙。 你的首要工作就是去问那个人他脑子里究竟是怎么想的。
LandyTan 2019-01-11
  • 打赏
  • 举报
回复
C++11的for语句
LL596214569 2019-01-11
  • 打赏
  • 举报
回复
引用 5 楼 lin5161678 的回复:
用 vector<vector<int> > arr; 举例子 最原始用迭代器

	for(vector<vector<int> >::iterator it = arr.begin(); it != arr.end(); ++it)
	{
		for(vector<int>::iterator iter = it->begin(); iter != it->end(); ++iter)
			cout << *iter << "\t";
		cout << endl;
	}
C++11 可以auto 不用写辣么长的类型
	for (auto it = arr.begin(); it != arr.end(); ++it)
	{
		for (auto iter = it->begin(); iter != it->end(); ++iter)
			cout << *iter << "\t";
		cout << endl;
	}
不喜欢写一堆for 可以 配合for_each + Lambda表达式
#include<algorithm>
	for (auto it = arr.begin(); it != arr.end(); ++it)
	{
		for_each(it->begin(), it->end(), [](int n){cout << n << "\t";	});
		cout << endl;
	}
额 这样循环怎么同时取到10个vector的值?
LL596214569 2019-01-11
  • 打赏
  • 举报
回复
引用 4 楼 zarelaky 的回复:
先根据nParamNum判断用哪个vector,再遍历对应的vector计算
nParamNum确定但是最后一个被用到的vector,不是用它来确定用哪个vector。 比如nParamNum = 3,那么用到的是前3个vector不是只用3个vector
lin5161678 2019-01-11
  • 打赏
  • 举报
回复
用 vector<vector<int> > arr; 举例子
最原始用迭代器

for(vector<vector<int> >::iterator it = arr.begin(); it != arr.end(); ++it)
{
for(vector<int>::iterator iter = it->begin(); iter != it->end(); ++iter)
cout << *iter << "\t";
cout << endl;
}


C++11 可以auto 不用写辣么长的类型
	for (auto it = arr.begin(); it != arr.end(); ++it)
{
for (auto iter = it->begin(); iter != it->end(); ++iter)
cout << *iter << "\t";
cout << endl;
}


不喜欢写一堆for 可以
配合for_each + Lambda表达式
#include<algorithm>
for (auto it = arr.begin(); it != arr.end(); ++it)
{
for_each(it->begin(), it->end(), [](int n){cout << n << "\t"; });
cout << endl;
}


zarelaky 2019-01-11
  • 打赏
  • 举报
回复
先根据nParamNum判断用哪个vector,再遍历对应的vector计算
zarelaky 2019-01-11
  • 打赏
  • 举报
回复
引用 2 楼 LL596214569 的回复:
[quote=引用 1 楼 zarelaky 的回复:]
nParamNum 哪来的?

nParamNum也是外界传过来的一个值,把它当做一个常量就好[/quote]
如果在多层循环外nParamNum就有固定值,且在循环遍历过程中nParamNum没有过修改,根据nParamNum和iter的对应关系,扒掉嵌套循环。
LL596214569 2019-01-11
  • 打赏
  • 举报
回复
引用 1 楼 zarelaky 的回复:
nParamNum 哪来的?
nParamNum也是外界传过来的一个值,把它当做一个常量就好
zarelaky 2019-01-11
  • 打赏
  • 举报
回复
nParamNum 哪来的?

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧