我遇到了一个可以简化的问题:
parameters: a, b
if (a > 5)
{
Print("Very well, a > 5");
if (b > 7)
Print("Even better, b > 7");
else
{
Print("I don't like your variables");
}
}
else
{
Print("I don't like your variables");
}
我只想使用一个else
而不是两个,因为它们是相同的代码。我想到的是创建一个额外的方法,它将返回组合true
`false`,但这是一个严重的过度杀伤。
另一种选择是goto
,但这会降低代码的可读性和不安全性。
这样做的方法是什么,避免多次检查相同的条件并使其尽可能可读?
答案 0 :(得分:21)
void doILikeYourVariables(int a, int b) {
if (a > 5) {
Print("Very well, a > 5");
if (b > 7) {
Print("Even better, b > 7");
return;
}
}
Print("I don't like your variables");
}
答案 1 :(得分:13)
布尔逻辑101:
public void test(int a, int b, int c) {
boolean good = true;
if (good = good && a > 5) {
System.out.println("Very well, a > 5");
}
if (good = good && b > 7) {
System.out.println("Even better, b > 7");
}
if (good = good && c > 13) {
System.out.println("Even better, c > 13");
}
// Have as many conditions as you need, and then
if (!good) {
System.out.println("I don't like your variables");
}
}
或者 - 如果你想要大量支票 -
enum Tests {
A_gt_5 {
@Override
boolean test(int a, int b, int c) {
return a > 5;
}
},
B_gt_7 {
@Override
boolean test(int a, int b, int c) {
return b > 7;
}
},
C_gt_13 {
@Override
boolean test(int a, int b, int c) {
return c > 13;
}
};
abstract boolean test (int a, int b, int c);
}
public void test(int a, int b, int c) {
boolean good = true;
for ( Tests t : Tests.values() ) {
good = good && t.test(a, b, c);
if (!good) {
break;
}
}
if (!good) {
System.out.println("I don't like your variables");
}
}
答案 2 :(得分:3)
if (a > 5)
{
Print("Very well, a > 5");
}
if(a > 5 && b >7)
{
Print("Even better, b > 7");
}
else
{
Print("I don't like your variables");
}
或
bool isEvenBetter = false;
if (a > 5)
{
Print("Very well, a > 5");
isEvenBetter = b > 7;
}
if(isEvenBetter)
{
Print("Even better, b > 7");
}
else
{
Print("I don't like your variables");
}
答案 3 :(得分:3)
实际上,对于您的情况,只有一个实例,您“喜欢”变量,即a>5 and b>7
时。在这种情况下,您只需要在最里面的if
中设置一个标志。像这样:
parameters: a, b
boolean good = false;
if (a > 5){
Print("Very well, a > 5");
if (b > 7){
Print("Even better, b > 7");
good = true;
}
}
if(!good){
Print("I don't like your variables");
}
删除多个else
时,只有一行(和一个变量),实际上甚至没有else
!)
我想说在这种情况下使用goto (或看起来支持它的任何东西)是可以接受的。
我同意“不受限制地使用goto”是不好的,因为它会混淆程序流程,但在某些情况下,最好使用goto,就像你描述的那样。
请参阅此问题:GOTO still considered harmful?
实际上,如果你考虑一下,提出一个(可能是自定义的)异常与goto相同,因为它会使程序流程跳转到某一点({{1 }或catch
)。
不使用goto的最佳理由是什么?这是因为可能是输入一行代码的多种方式。这也是为什么有些人不推荐多次退货的原因。但在你的情况下,我们确实想要在多个点退出,因此需要功能。
受限制的goto(例如Java中的异常处理,只能“转到”“catch”行)很好。
我并不是说你应该使用goto,但我正在解决你说“goto is bad”的问题,同时也会为答案池做出贡献。< / p>
答案 4 :(得分:2)
你可以改变一个州:
bool good = a > 5;
if(good)
{
Print("Very well, a > 5");
good = b > 7;
if(good) {
Print("Even better, b > 7");
}
}
if( ! good) {
Print("I don't like your variables");
}
答案 5 :(得分:2)
如何在休息时使用do
。这实际上是执行goto
的一种偷偷摸摸的方式,尽管您可以将其视为由多个if
语句组成的过滤器,如果没有if
语句,则默认为最后一位被击中了。
parameters: a, b
do {
if (a > 5)
{
Print("Very well, a > 5");
if (b > 7)
{
Print("Even better, b > 7");
break;
}
}
Print("I don't like your variables");
} while (false);
编辑 - 关于重新定位语言
许多人反对这种专门用来解决特定问题的做法。主要的反对意见似乎是它似乎是一个循环,但实际上并不是一个循环,因此这个结构属于一种uncanny valley循环使用。换句话说,&#34;它只是自然而已。&#34;
我同意这是一种不常见的用法,确实应该有一些注释来确定这是一个过滤器,使用do while创建一个块,允许在达到决策树分支终点时使用break语句。这就是这个,一个硬编码的forward traversal decision tree没有回溯由一系列决定组成。在决策过程中的任何一点,我们都可以通过一个决定突破,或者通过一个默认的决定,包括根本没有做出任何决定。
可以说任何需要评论可理解的来源都不是好的代码。另一方面,几乎所有编程语言都有某种方式来插入注释的原因是因为当您在六个月后回来进行更改时,注释源代码非常有用。
这种方法的好处在于它创建了一个局部范围,以便在决策过程中所需的变量可以被正确地构造和破坏。
在某些方面,它有点像lambda,我怀疑有人会反对它,它可以用在不支持lambda的语言中。换句话说,它与try catch相似。
仔细阅读网络可以找到很多文章,其中有人使用编程语言的方式与其原始设计意图不同,例如using C++ in a functional programming style上的这篇文章或using object oriented practices with the C programming language上的这本在线书籍3}}
所有程序员都有某些风格或语言使用习惯。源代码审查和阅读其他人的源代码可以带来的好处是学习使用编程语言的不同方式。
这不是一个棘手的代码,就像人们会发现Obfuscated C Programming contest的条目一样。这很简单。
编辑:比转到更好?
关于这种不寻常的使用方式的一个问题是,&#34;为什么不只是使用goto?&#34;阅读Dijkstra's essay of Go To Statement Considered Harmful以及此blog discussion on the essay and the goto statement,我们可以看到使用带有break语句的循环有几个很好的特性,这些语句不是goto及其相关标签的特征。
主要特征,特别是这个例子是单向流动,其中有明确的开始和明确的结束。通过移动goto标签不会无意中更改程序流程。使用goto标签作为跳转创建原本不打算的依赖项的适当位置,函数中的其他地方没有危险。读取代码时,每个程序员都知道在中断的地方,你要离开循环,离开循环时,你会在循环结束后进入源代码行。结果是你有一个很好的清洁知识块,可以标记为&#34;找出要打印的文本&#34;
答案 6 :(得分:2)
看看所有的答案,我会这样写,并保留两个。将它复杂化毫无意义。
parameters: a, b
if (a > 5)
{
Print("Very well, a > 5");
if (b > 7)
Print("Even better, b > 7");
else
DontLikeIt();
}
else
{
DontLikeIt();
}
并有一个方法,DontLikeIt(),打印你想要的响应。
答案 7 :(得分:1)
只是为了好玩!
class VariableLiker {
private:
bool isGood_;
public:
VariableLiker() : isGood_(false) {}
void checkA(int a) {
if (a > 5) {
Print("Very well, a > 5");
isGood_ = true;
}
}
void checkB(int b){
if (isGood_ && b > 7)
Print("Even better, b > 7");
else
Print("I don't like your variables");
}
};
//...
VariableLiker variableLiker;
variableLiker.checkA(a);
variableLiker.checkB(b);
答案 8 :(得分:1)
没有休息或转到的另一种方式是:
int c = (new[] { a > 5 ,a > 5 && b > 7 }).Count(x=>x);
if (c > 0)
{
Print("Very well, a > 5 ");
}
if (c > 1)
{
Print("Even better, b > 7");
}
else
{
Print("I don't like your variables");
}
答案 9 :(得分:1)
代码的有趣之处在于,即使它喜欢 a ,如果 b ,“也不喜欢你的变量”然后还不够好。
显然,你实际上并不担心代码中有两个 else 语句;它是您希望避免的“不喜欢”代码的重复。如果您不介意丢弃 b 的值,以下内容将起到作用。
if (a > 5)
Print("Very well, a > 5");
else
b = 0;
if (b > 7)
Print("Even better, b > 7");
else
Print("I don't like your variables");
如果您需要保留 b 的值,那么您可以使用其他变量。
var evenBetter = (b > 7);
if (a > 5)
Print("Very well, a > 5");
else
evenBetter = false;
if (evenBetter)
Print("Even better, b > 7");
else
Print("I don't like your variables");
这是一个版本,在需要之前不会预先计算 b 的优点。当测试成本高或者可能产生副作用时,这样做会更好。它也消除了 else ,如果真的很重要的话。 ; - )
var evenBetter = false;
if (a > 5)
{
Print("Very well, a > 5");
evenBetter = (b > 7);
}
if (evenBetter)
Print("Even better, b > 7");
else
Print("I don't like your variables");
这种“拆分”方法的缺点是,一个草率的读者可能会认为第二个 if 语句与 a 无关,因此没有注意到 <不喜欢你的变量
答案 10 :(得分:0)
你有没有试过像
这样的东西string badResponse = "I don't like your variables";
string goodReponse = "Very well, a > 5";
string betterReponse = "Even better b > 7";
(a > 5) ? ((b>7) ? Print(betterReponse) : Print(goodReponse)) : Print(badResponse);
答案 11 :(得分:0)
if((a <5)||(b <7)) 打印(&#34;我不喜欢你的变量。&#34;);
反转逻辑,并将其修补。你正在做的是&#34;和&#34 ;;因此,首先检查无效案例,然后在其下方进行额外检查。这也符合DRY原则。
答案 12 :(得分:0)
if (a > 5 && b > 7)
{
Print("Very well, a > 5");
Print("Even better, b > 7");
}
else
{
if (a > 5)
{
Print("Very well, a > 5");
}
Print("I don't like your variables");
}
答案 13 :(得分:0)
string msgFirstPart, msgSecondPart = "I don't like your variables";
if (a > 5) {
msgFirstPart = "Very well, a > 5\n";
if (b > 7)
msgSecondPart = "Even better, b > 7";
}
Print(msgFirstPart + msgSecondPart);
答案 14 :(得分:0)
好吧,如果您使用的是C ++,则可以使用0 else
和0 if
:
switch ( ( a > 5 ) + ( ( b > 7 ) << 1 ) )
{
case 1:
printf ( "Very well, a > 5" );
case 0:
case 2:
printf ( "I don't like your variables" );
break;
case 3:
printf ( "Very well, a > 5" );
printf ( "Even better, b > 7" );
break;
}
C#版本有一些隐形的if三元运算符形式的语句:
(对{Java使用System.out.print
)
switch ( ( a > 5 ? 1 : 0 ) + ( b > 7 ? 2 : 0 ) )
{
case 1:
Console.WriteLine ( "Very well, a > 5" );
Console.WriteLine ( "I don't like your variables" );
break;
case 0:
case 2:
Console.WriteLine ( "I don't like your variables" );
break;
case 3:
Console.WriteLine ( "Very well, a > 5" );
Console.WriteLine ( "Even better, b > 7" );
break;
}
答案 15 :(得分:-1)
使用? :
运算符,否则不需要。
因此,相同的代码将被删除,并且图片中不会有其他方法或goto
。
注意:但是,如果a > 5
和b < 7
,则无法打印完整的结果。
在这种情况下,不会打印额外"I don't like your variables"
。
示例:
string result = "I don't like your variables";
if (a > 5)
{
result = (b > 7) ? "Even better, b > 7" : "Very well, a > 5";
}
Print(result);