需要有关重构深度嵌套代码的帮助
Need help on refactoring a deeply nested code
#include <iostream>
using namespace std;
int main()
{
int range = 20;
int totalCombinations = 0;
for(int i=1; i<=range-2; i++)
{
if(range>i)
{
for(int j=1; j<=range-1; j++)
if(j>i)
{
for(int k=1; k<=range-1; k++)
if(k>j)
{
for(int l=1; l<=range-1; l++)
if(l>k)
{
for(int m=1; m<=range-1; m++)
if(m>l)
{
for(int f=1; f<=range; f++)
if(f>m)
{
cout << " " <<i<< " " <<j<< " " <<k<< " " <<l<< " " <<m<< " " <<f;
cin.get(); //pause
totalCombinations++;
}
}
}
}
}
}
}
cout << "TotalCombinations:" << totalCombinations;
}
if(range>i)
为什么不在 哦,我倒过来说了,但重点是——你可以很容易地将其重构为range
处启动i
并避免该问题呢for
条件的一部分。不需要额外的条件。
if(j>i)
为什么不在i
启动j
呢?
(对其他两个回路重复)
这样就可以去掉一半的嵌套。就循环本身而言,我建议对它们使用提取方法。
您可以做的第一件事是使用continue
:
for(int i=1; i<=range-2; i++) {
{
if(range<=i) {
continue;
}
for(int j=1; j<=range-1; j++) {
if(j<=i) {
continue;
}
//etc for all inner loops
}
}
这将大大减少嵌套,IMO将提高可读性。
与重构任何东西的方式相同。你首先要弄清楚代码正在执行。在这种情况下,许多测试都是不相关的,并且每个循环基本上都做相同的事情。你已经解决了一个非常一个更普遍问题的具体情况(非常草率)。锻炼该问题的通用算法将导致更干净、更简单解决方案,以及更通用的解决方案。类似这样的东西:
class Combin
{
int m;
int n;
int total;
std::vector<int> values;
void calc();
void dumpVector() const;
public:
Combin( int m, int n ) : m(m), n(n), total(0) {}
int operator()() { total = 0; values.clear(); calc(); return total; }
};
void
Combin::calc()
{
if ( values.size() == m ) {
dumpVector();
++ total;
} else {
values.push_back( values.empty() ? 0 : values.back() + 1 );
int limit = n - (m - values.size());
while ( values.back() < limit ) {
calc();
++ values.back();
}
values.pop_back();
}
}
void
Combin::dumpVector() const
{
for (std::vector<int>::const_iterator iter = values.begin(); iter != values.end(); ++ iter )
std::cout << ' ' << *iter + 1;
std::cout << 'n';
}
int main()
{
Combin c( 6, 20 );
std::cout << "TotalCombinations:" << c() << std::endl;
return 0;
}
上面唯一真正值得评论的是计算calc
中的limit
,这实际上只是一个优化;你可以使用n
并获得相同的结果(但您会递归更多)。
您会注意到,在您的原始版本中循环或多或少是任意的:系统地使用range
工作,或者你可以算出我用于limit
的公式(将导致每个循环的不同结束条件。
此外,我的代码使用了半开区间,它在C和C++我想,一旦你习惯了它们,你就会发现它们很多更容易推理。
我的C++很生疏,所以让我给您举一个C#示例。任何数量的嵌套循环都可以用一个替换,如下所示:
public void ManyNestedLoopsTest()
{
var limits = new[] {2, 3, 4};
var permutation = new[] {1, 1, 0};
const int lastDigit = 2;
var digitToChange = lastDigit;
while(digitToChange >= 0)
{
if (permutation[digitToChange] < limits[digitToChange])
{
permutation[digitToChange]++;
digitToChange = lastDigit;
PrintPermutation(permutation);
continue;
}
permutation[digitToChange--] = 1;
}
}
private void PrintPermutation(int[] permutation)
{
for(int i=0;i<3;i++)
{
Console.Write(permutation[i]);
Console.Write(" ");
}
Console.WriteLine(" ");
}
相关文章:
- 嵌套在类中时无法设置成员数据
- 无法访问嵌套类.类的使用无效
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- Clang拒绝类模板的嵌套类仅通过专门化定义的代码是正确的吗
- 用于更简洁代码的嵌套命名空间
- 嵌套矢量化 OpenMP 循环,在最内层循环中具有多行代码
- OpenMP 嵌套循环,每个"for"循环之间都有代码
- gcc segfault在编译嵌套参数包代码上
- 在cpp中创建嵌套对象.下面的伪代码中的函数调用序列是什么
- C++ 嵌套'if'语句中的所有代码都会运行,即使这会更改外部语句的布尔值?
- C-do{.}while(0);可以从代码中删除,不包括嵌套的if-else用法
- 如何让代码存在于两个或多个非嵌套命名空间的范围内
- 代码在嵌套开关中选择的每个情况和错误C4244在c++中从double转换为float后停止/结束
- 如何连接来自c++代码的嵌套qml项的信号
- 如何重写复杂的c++代码行(嵌套的三元操作符)
- 为什么具有多个嵌套循环的代码可以在 GCC 上立即完成,但在 VS 上需要很长时间
- 为球体的体积加速代码(嵌套while循环)
- 如何使用嵌套枚举实现代码重用
- 在c++中使用嵌套注释来快速(取消)激活代码块是有危险的
- 需要有关重构深度嵌套代码的帮助