如何减少if语句

下面的程序可以根据需要运行,但是如何减少if语句的数量。 有人告诉我,如果你的函数包含2个或更多if语句,那么你做错了。 有什么建议么? 我已经尝试过使用switch语句,但由于案例不能成为布尔值,因此无效。

for(int i = 1; i < 100; i++) { if(i % 10 == 3) { System.out.println("Fizz" + "(" + i + ") 3%10"); } if(i / 10 == 3) { System.out.println("Fizz" + "(" + i + ") 3/10"); } if(i % 10 == 5) { System.out.println("Buzz" + "(" + i + ") 5%10"); } if(i / 10 == 5) { System.out.println("Fizz" + "(" + i + ") 5/10"); } if(i / 10 == 7) { System.out.println("Fizz" + "(" + i + ") 7/10"); } if(i%10 == 7) { System.out.println("Woof" + "(" + i + ") 7%10"); } if(i % 3 == 0) { System.out.println("Fizz" + "(" + i + ") 3%==0"); } if(i % 5 == 0) { System.out.println("Buzz" + "(" + i + ")5%==0"); } if(i % 7 == 0) { System.out.println("Woof" + "(" + i + ")7%==0"); } if( (i % 7 !=0 ) && (i % 3 !=0 ) && (i % 5 !=0 ) && (i % 10 !=3) && (i % 10 !=5 ) && (i%10 !=7 ) ) System.out.println(i); } 

如何为案例创建方法:

  public void printIfMod(int value, int mod){ if (value % 10 == mod) System.out.println(...); } public void printIfDiv(int value, int div){ if (value / 10 == div) System.out.println(...); } 

然后, if你有一组调用两个方法,而不是一堆。 您甚至可以创建一个调用上述两种方法的方法。

  public void printIf(int value, int div){ printIfMod(value, div); printIfDiv(value, div); } for(int i = 1; i < 100; i++) { printIf(i, 3); printIf(i, 5); .... } 

在上面的代码中, ifs的数量对我来说比重复代码的数量少。

使用两个switch语句略有改进

 switch(i / 10){ case 3: // do something break; case 5: // do something else break; case 7: // do something else break; } switch(i % 10){ case 3: // do something break; case 5: // do something else break; case 7: // do something else break; } 

不幸的是,每个除数你需要一个switch语句。

或者,你可以拥抱OOP并提出这样的抽象:

 public abstract class Processor { private final int divisor; private final int result; private final boolean useDiv; // if true, use /, else use % public Processor(int divisor, int result, boolean useDiv) { this.divisor = divisor; this.result = result; this.useDiv = useDiv; } public final void process(int i){ if ( (useDiv && i / divisor == result) || (!useDiv && i % divisor == result) ){ doProcess(i); } } protected abstract void doProcess(int i); } 

样品用法:

 public static void main(String[] args) { List processors = new ArrayList<>(); processors.add(new Processor(10, 3, false) { @Override protected void doProcess(int i) { System.out.println("Fizz" + "(" + i + ") 3%10"); } }); // add more processors here for(int i = 1; i < 100; i++){ for (Processor processor : processors) { processor.process(i); } } } 

一般来说,拥有大量if语句的代码看起来很可疑。 可疑并不一定意味着错误。 如果问题陈述有不相同的条件要检查(即你不能将它们分组),那么你必须像你一样独立完成它们。

在你的情况下,你必须检查divisibility而不能推断另一个(即如果x可以被7整除,它并不意味着它也可以被5整除,等等……)。 你正在使用的所有数字都是故意选择的素数,所以这就是你进入这个数字的原因。

例如,如果他们说过,请检查可分性为2,3和6.然后你可以先检查6,因为那时你也可以暗示2和3的可分性。反之亦然,检查2和3并暗示它也可被6整除。如果所有数字都是素数,那么你就不能暗示。 所以你的代码必须单独检查所有内容。

一个积极的副作用是它使您的意图易于在您的代码中阅读(因为它都是明确的)。

我的两分钱……

Enum非常适合这里。 它们允许您将function封装在一个位置,而不是将其传播到整个流控制中。

 public class Test { public enum FizzBuzz { Fizz { @Override String doIt(int n) { return (n % 10) == 3 ? "3%10" : (n / 10) == 3 ? "3/10" : (n / 10) == 5 ? "5/10" : (n / 10) == 7 ? "7/10" : (n % 3) == 0 ? "3%==0" : null; } }, Buzz { @Override String doIt(int n) { return (n % 10) == 5 ? "5%10" : (n % 5) == 0 ? "5%==0" : (n / 10) == 3 ? "3/10" : (n / 10) == 5 ? "5/10" : (n / 10) == 7 ? "7/10" : null; } }, Woof { @Override String doIt(int n) { return (n % 10) == 7 ? "7%10" : (n % 7) == 0 ? "7%==0" : null; } }; // Returns a String if this one is appropriate for this n. abstract String doIt(int n); } public void test() { // Duplicates the posters output. for (int i = 1; i < 100; i++) { boolean doneIt = false; for (FizzBuzz fb : FizzBuzz.values()) { String s = fb.doIt(i); if (s != null) { System.out.println(fb + "(" + i + ") " + s); doneIt = true; } } if (!doneIt) { System.out.println(i); } } // Implements the game. for (int i = 1; i < 100; i++) { boolean doneIt = false; for (FizzBuzz fb : FizzBuzz.values()) { String s = fb.doIt(i); if (s != null) { if ( doneIt ) { System.out.print("-"); } System.out.print(fb); doneIt = true; } } if (!doneIt) { System.out.print(i); } System.out.println(); } } public static void main(String args[]) { try { new Test().test(); } catch (Throwable t) { t.printStackTrace(System.err); } } } 

我已经开始写一个涉及代码的答案,但是很多人都打败了我。 我要说的一件事还没有提到的是,你所指的这个特定的代码度量被称为圈复杂度 ,并不是一个可怕的坏事。

简而言之,它指的是一个方法在执行时可以采用的不同路径的数量,虽然它在您发布的代码剪切中非常高,并且有很多很好的提示/解决方案来减少它已被建议,个人我认为即使在它的当前forms中,代码也是非常易读的 – 这是一个奖励。 它可以减少相当数量并且仍然可读,但我的观点是这样的指标并不是一切,有时候因为它更具可读性而有更多if语句可能更简单 – 可读性降低了出错的可能性,使调试更容易

哦,我会替换最后一节:

 if( (i % 7 !=0 ) && (i % 3 !=0 ) && (i % 5 !=0 ) && (i % 10 !=3) && (i % 10 !=5 ) && (i%10 !=7 ) ) System.out.println(i); 

通过在调用任何替换语句时使用boolean标志(例如replacement replaced = true ,上面的语句将折叠为:

 if (!replaced) System.out.println(i); 

我会说,你问的是错误的问题。 我认为你应该问的问题是:“我怎样才能重写这段代码,以便人类更容易理解?”

信条“消除if语句”是实现这一目标的一般想法,但它在很大程度上取决于上下文。

可悲的事实是,许多答案以“使其更简单”为幌子来混淆这种非常简单的算法。 永远不要引入一个对象来消除一些if语句。 在我的工作中,大多数代码由比原始作者更少理解体系结构,数学和代码的人维护,因此引入额外的构造和复杂性以将代码从50个物理行减少到30个物理行,但使其成为4时间更难理解不是胜利。

你的代码是重复的。 使用循环重构它:

 for (int i = 1; i < 100; i++) { boolean found = false; // used to avoid the lengthy test for "nothing found" for (int j = 3; j <= 7; j += 2) { // loop 3, 5, 7 if (i % 10 == j) { System.out.println("Fizz" + "(" + i + ") "+j+"%10"); found = true; } if (i / 10 == j) { System.out.println("Fizz" + "(" + i + ") "+j+"/10"); found = true; } if (i % j == 0) { System.out.println("Fizz" + "(" + i + ") "+j+"%==0"); found = true; } } if (!found) { System.out.println(i); } } 

您可以创建多个开关:

 switch (i/10) { case 3: System.out.println("Fizz" + "(" + i + ") 3/10"); break; case 5: System.out.println("Fizz" + "(" + i + ") 5/10"); break; case 7: System.out.println("Fizz" + "(" + i + ") 7/10"); break; default: break; } switch (i%10) { case 3: System.out.println("Fizz" + "(" + i + ") 3%10"); break; case 5: System.out.println("Buzz" + "(" + i + ") 5%10"); break; case 7: System.out.println("Woof" + "(" + i + ") 7%10"); break; default: break; } 

另一种情况仍然需要使用if语句。
Oracle添加了在Java 7中使用String switch语句。也许boolean switch语句将在稍后出现。

 public class Test { public static void main(String[] args) { final int THREE = 3; final int FIVE = 5; final int SEVEN=7; final int ZERO = 0; for (int i = 1; i < 100; i++) { modOperation("Fizz", i, THREE); divideOperation("Fizz", i, THREE); modOperation("Fizz", i, FIVE); divideOperation("Buzz", i, FIVE); modOperation("Woof", i, SEVEN); divideOperation("Fizz", i, SEVEN); modOperation("Fizz", i, ZERO); divideOperation("Fizz", i, ZERO); } } private static void divideOperation(String sound, int i, int j) { if (i / 10 == j) // you can add/expand one more parameter for 10 and later on 3 in this example. { System.out.println(sound + "(" + i + ") "+j+"/10"); } } private static void modOperation(String sound, int i, int j) { if (i % 10 == j) { System.out.println(sound + "(" + i + ") "+j+"%10"); } } } 

所以现在你少了

Interesting Posts