我正在开发一个分析和预测波形模式的项目,但问题是嵌套if / else的代码变得越来越难以管理,这里是片段:
for (int x = 1; x <= 24; x++)
{
if ((15 <= Angles[x]) && (Angles[x] <= 30))
{
if(x<=6)
{
counter=counter+4;
if (edges[x] < edges[x+2]) { counter = counter - 4; }
else{counter=counter+5; };
if (Angles[x] < Angles[x + 2]) { counter = counter - 6; }
else{counter=counter + 4; };
if ((edges[x+1] - edges[x]) < (edges[x + 3] - edges[x + 2])) { counter= counter - 6; }
else{counter-counter + 5; };
if (gradient[x] < gradient[x + 2]) { counter = counter - 6; }
else{counter=counter + 5; };
};
if((7<=x)&&(x<=12))
{
counter = counter - 10;
if (edges[x] < edges[x+2]) { counter = counter - 5; }
else{counter=counter + 6; };
if (Angles[x] < Angles[x + 2]) { counter = counter - 7; }
else{counter=counter + 6; };
if ((edges[x+1] - edges[x]) < (edges[x + 3] - edges[x + 2])) { counter =
counter - 6; }
else{counter-counte+7; };
if (gradient[x] < gradient[x + 2]) { counter = counter - 6; }
else{counter=counter+8; };
};
if((13<=x)&&(x<=18))
{
counter = counter - 30;
if (edges[x] < edges[x+2]) { counter = counter - 7; }
else{counter=counter + 6; };
if (Angles[x] < Angles[x + 2]) { counter = counter - 7; }
else{counter=counter + 5; };
if ((edges[x+1] - edges[x]) < (edges[x + 3] - edges[x + 2])) { counter =
counter - 7; }
else{counter-counter+5; };
if (gradient[x] < gradient[x + 2]) { counter = counter + 5; }
else{counter=counter + 5; };
};
//there are more waves classification and weightage to come//
if ((30 <= Angles[x]) && (Angles[x] <= 45)){}.....
if ((45 <= Angles[x]) && (Angles[x] <= 60)){}.....
if(60 < Angles[x]){}....
};
角度是存储波角值的容器。 边缘是波峰和波谷。 gradient包含wave的渐变值 counter是当前模式的权重。 值以串行方式存储在向量中。
这只是一个粗略的剥离片段(如果找到,则忽略语法错误)。 每个模式都包含一个for循环,其中包含嵌套的if / else。 还有13种模式。
我已经越过了5000行,只是写了if / else for循环。你能帮助我让这个更容易管理吗?
答案 0 :(得分:3)
而不是
if(x<=6)
{
counter=counter+4;
if (edges[x] < edges[x+2]) { counter = counter - 4; }
else{counter=counter+5; };
if (Angles[x] < Angles[x + 2]) { counter = counter - 6; }
else{counter=counter + 4; };
if ((edges[x+1] - edges[x]) < (edges[x + 3] - edges[x + 2])) { counter= counter - 6; }
else{counter-counter + 5; };
if (gradient[x] < gradient[x + 2]) { counter = counter - 6; }
else{counter=counter + 5; };
};
你可以写
if(x<=6)
{
counter = counter
+ 4
+ ((edges[x] < edges[x+2]) ? -4 : 5)
+ ((Angles[x] < Angles[x + 2]) ? -6 : 4)
+ (((edges[x+1] - edges[x]) < (edges[x + 3] - edges[x + 2])) ? -6 : 5)
+ ((gradient[x] < gradient[x + 2]) ? -6 : 5)
};
如果您可以将条件放在自己的功能中,代码也会变得更加清晰。
我看到很多条件,比如array [x]&lt;阵列[X + 2]。您可以定义lambdas,如
auto raisingEdge = [&](int x) { return edges[x] < edges[x+2]; };
并像
一样使用它counter += raisingEdge(x) ? -4 : 5;
这可以使您的代码更具可读性:
if(x<=6)
{
counter = counter
+ 4
+ (raisingEdge(x) ? -4 : 5)
+ (raisingAngle(x) ? -6 : 4)
+ (raisingEdgeDelta(x) ? -6 : 5)
+ (raisingGradient(x) ? -6 : 5)
};
(这些名字只是为了展示这个概念;我不知道也不关心这些价值究竟是什么)
答案 1 :(得分:2)
您还可以将lambda与stencil push
语义结合使用。
对于你的第一对if语句你可以做这样的事情:
condition ? if : else
您的其他auto comp = [&counter](int n, int m, int val1, int val2) { return n < m ? counter + val1 : counter + val2; };
counter = comp(edges[x], edges[x + 2], -4, 5);
counter = comp(Angles[x], Angles[x + 2], -6, 4);
也是如此,您可以添加它们。
答案 2 :(得分:2)
我不确定你的if
... else if
的小序列是无法管理的还是低效的(恕我直言,它是可管理和有效的,但需要更好的缩进;请考虑使用类似的工具重新格式化代码https://github.com/phpDocumentor/phpDocumentor2/issues/1834)。
除了astyle和兼容(例如GCC)编译器的其他答案之外,您可能考虑使用某些Clang:
switch
使用language extension(这是我的偏好,并且非常易读),所以像
switch(x) {
case 1 ... 6:
{
counter=counter+4;
if (edges[x] < edges[x+2]) { counter = counter - 4; }
else {counter=counter+5; };
if (Angles[x] < Angles[x + 2]) { counter = counter - 6; }
else{counter=counter + 4; };
if ((edges[x+1] - edges[x]) < (edges[x + 3] - edges[x + 2]))
{ counter= counter - 6; }
else{counter-counter + 5; };
if (gradient[x] < gradient[x + 2]) { counter = counter - 6; }
else{counter=counter + 5; };
};
break;
goto
当然,您需要(有意识地)决定使用C ++ 11(请参阅labels as values)或C ++ 14标准未定义的语言扩展。 (上面的代码甚至无法在某些Microsoft编译器上编译,因为它是非标准的。)
如果使用n3337和/或GCC,请不要忘记启用所有警告和调试信息,例如Clang -Wall -Wextra -g
至g++
或clang++
我已经越过了5000行,只是写了if / else for循环。
您可以通过定义小的特定内部函数(可能是static
个函数或私有成员函数)来决定to pass您的代码来处理每个案例。根据经验,尽量避免数千行的大量手写功能:定义每个最多几百行的较小内部函数,并适当地调用它们 - 也许只需要一次。即使只调用一次内部函数,在函数中放置几百行的块也常常(但并不总是)有用。由你明智地组织,并为你的内部职能提供有意义的名称。
C ++中的编码也是(许多)惯例和习惯的问题。我建议你研究一些refactor类似的(源于目标,精神上)的源代码,以获得灵感。 (您将在free software,github和其他地方使用C ++找到许多自由软件项目。
在sourceforge中,您甚至可以考虑从其他内容生成您的C ++代码(更高级别,特定于您的方法)。哟可能想要在其中生成some cases。也许这种#line
directives方法在你的情况下是值得的(在尝试之前一定要阅读metaprogramming)。
答案 3 :(得分:1)
除了数字之外,每个块(以counter = counter - 10;
行开头)似乎相同。在这种情况下,我肯定会选择功能。数字将成为其参数。如果使它成为同一个类的方法,并且块中使用的变量是类属性,则新方法可以轻松访问它们。
这肯定有助于代码的可管理性。如果您在计算中发现错误,则只需更正一个位置。
经验法则:如果您不止一次地复制粘贴代码的某些部分,您应该考虑使其成为可以重复使用的实体,如宏,函数或类。
另请参阅:Wikipedia – Don't repeat yourself
顺便说一下,
counter -= 10;
(以及所有类似案例)可以缩短为
NameError Traceback (most recent call last)
<ipython-input-26-d21b1cb0fcab> in <module>()
19 download('http://data.mxnet.io/data/caltech-256/caltech-256-60-train.rec')
20
---> 21 upload_to_s3('train', 'caltech-256-60-train.rec')
<ipython-input-26-d21b1cb0fcab> in upload_to_s3(channel, file)
13 data = open(file, "rb")
14 key = channel + '/' + file
---> 15 s3.Bucket(bucket).put_object(Key=key, Body=data)
16
17
NameError: name 'bucket' is not defined