如何减少if语句

Cal*_*r99 24 java if-statement fizzbuzz switch-statement

下面的程序可以根据需要运行,但是如何减少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);
    }
Run Code Online (Sandbox Code Playgroud)

Joh*_*n B 49

如何为案例创建方法:

 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(...);
 }
Run Code Online (Sandbox Code Playgroud)

然后,而不是一堆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);
      ....
 }
Run Code Online (Sandbox Code Playgroud)

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

  • 事实上,你*只需要迭代除数,并且不需要将其提取到一个方法中,在这种情况下将只有一个调用站点. (3认同)
  • 您需要添加"声音",如AmitG的答案.`public void printIfXyz(string sound,int value,int numerator){...}`.示例中的代码并不干净3 = fizz/5 = buzz/7 = woof.(这是故意的还是故意的是未知的). (2认同)

Sea*_*oyd 26

使用两个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;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,每个除数你需要一个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);
}
Run Code Online (Sandbox Code Playgroud)

样品用法:

public static void main(String[] args) {
    List<Processor> 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);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)


mpr*_*vat 12

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

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

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

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

我的两分钱......


Old*_*eon 8

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

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);
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

  • +1虽然我喜欢枚举方法,但实际上我无法忍受嵌套的条件运算符.但这可能是个人偏好.从来没有嵌套条件运算符只是我的经验法则. (2认同)

Mat*_*lor 7

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

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

哦,我会替换最后一节:

if( (i % 7 !=0 ) && (i % 3 !=0 ) && (i % 5 !=0 )
            && (i % 10 !=3) && (i % 10 !=5 ) && (i%10 !=7 ) )
        System.out.println(i);
Run Code Online (Sandbox Code Playgroud)

通过使用布尔标志,例如replaced = true每当调用任何替换语句时,上述语句都会折叠为:

if (!replaced)
      System.out.println(i);
Run Code Online (Sandbox Code Playgroud)


Joh*_*ohn 7

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

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

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


Boh*_*ian 5

你的代码是重复的.使用循环为您重构它:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @ugoren所以它是......固定的.`<借口>`我在我的iPhone上输入了代码`</ excuse>` (2认同)
  • @Bohemian 100尊重点在你的iPhone上编写代码 (2认同)
  • 强烈反对.你只是让代码更难阅读和测试bug.代码长度!=代码质量. (2认同)