24

以下のプログラムは必要に応じて機能しますが、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);
    }
4

9 に答える 9

52

ケースのメソッドを作成するのはどうですか:

 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次に、一連の呼び出しの代わりに、2 つのメソッドを呼び出します。上記の両方を呼び出す単一のメソッドを作成することもできます。

 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は、繰り返されるコードの量よりも、回数の方が問題ではありません。

于 2013-05-21T12:18:55.220 に答える
26

これは、2 つの 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;
}

残念ながら、除数ごとに 1 つの 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<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);
        }
    }

}
于 2013-05-21T12:19:15.597 に答える
8

ここでは列挙型が適しています。フロー制御全体に機能を分散させるのではなく、機能を 1 つの場所にカプセル化することができます。

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

}
于 2013-05-21T12:32:01.407 に答える
7

私はコードに関する回答を書き始めましたが、非常に多くの人が私を打ち負かしました。まだ言及されていないことの1つは、あなたが言及しているこの特定のコードメトリックは循環的複雑度と呼ばれ、ひどく悪いことではないということです。

要するに、それはメソッドが実行されたときに取ることができるさまざまなパスの数を指し、あなたが投稿した断片化されたコードではかなり高いですが、個人的に提案されたそれを減らすための良いヒント/解決策がたくさんあります現在の形式でも、コードは非常に読みやすいと思います。これはおまけです。かなりの量を減らしても読みやすくすることができますが、私のポイントは、そのようなメトリックがすべてではないということです.読みやすいので、多くのステートメントを持つ方が簡単な場合があります.if読みやすさは間違いを犯す可能性を減らします.デバッグがはるかに簡単になります

ああ、私はこの最後のセクションを置き換えます:

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

replaced = true置換ステートメントのいずれかが呼び出されるたびにブール値フラグを使用すると、上記のステートメントは次のように折りたたまれます。

if (!replaced)
      System.out.println(i);
于 2013-05-21T12:27:56.037 に答える
7

あなたは間違った質問をしていると私は主張します。あなたが尋ねるべきだと私が思う質問は、「人間がより簡単に理解できるように、このコードをどのように書き直すことができるでしょうか?」ということです。

「ifステートメントを排除する」という信条は、これを達成するための一般的なアイデアですが、コンテキストに大きく依存します。

悲しいことに、答えの多くは、この非常に単純なアルゴリズムを「より単純にする」ことを装って難読化しています。いくつかの if ステートメントを排除するためにオブジェクトを導入しないでください。私の仕事では、ほとんどのコードは、元の作成者よりもアーキテクチャ、数学、およびコードについてはるかに理解していない人々によって維持されているため、追加の構造と複雑さを導入して、コードを 50 物理行から 30 物理行に減らしますが、4理解するのが何倍も難しいことは勝利ではありません。

于 2013-05-21T13:51:56.043 に答える
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);
    }
}
于 2013-05-21T12:59:14.340 に答える
0
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");
        }
    }
}

だから今、あなたはより少ないですif

于 2013-05-21T12:31:56.053 に答える