2013-05-21 20 views
24

以下のプログラムは必要に応じて機能しますが、if文の量を減らすにはどうすればよいですか?あなたの関数が2つ以上のif文を含んでいれば、あなたはそれが間違っていると言われました。助言がありますか? switch文を使ってみましたが、大文字小文字をブール値にすることはできないため、これはうまくいきませんでした。if文を減らすには

例のための方法を作成する方法について
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); 
    } 
+0

それは、すべてのアプリケーションを設計する方法についてです。 – OsakaHQ

+4

これは宿題かテストの質問ですか? – JayDM

+0

そのようなインタビューテストの質問の種類。 – Calgar99

答えて

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

そして、代わりに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の数が繰り返されるコードの量よりも私には問題が少ないです。

+0

また、 、3,5,7などこれらの繰り返しを避けるために –

+3

実際には、除数を繰り返し処理する必要があり、その場合は単一の呼び出しサイトを持つメソッドに抽出する必要はありません。 –

+2

例のコードはきれいではありません3 = fizz/5 =この例のコードは正しくありません。バズ/ 7 =偽(それが意図的であるか意図的であるかは不明です) – WernerCD

26

ここでは残念ながらあなたは除数につき1 switch文が必要になります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; 
} 

を使用して若干の改善です。

また、あなたは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); 
     } 
    } 

} 
12

は、一般的に言えば、それは本当だというif文をたくさん持っているコード疑わしいと思われる。怪しいとは必ずしも間違っているとは限りません。問題のステートメントがチェックするための分離条件がある場合(つまり、それらをグループ化できない場合)、実行しているように独立して実行する必要があります。

あなたのケースでは、他のものから推論することができずに除算をチェックする必要があります(つまり、xが7で割り切れる場合、5で割り切れるなどというわけではありません) 。あなたが使用しているすべての数字は意図的にプライムされているので、これがあなたがこれに入っている理由です。

たとえば、2、3、6で割り切れているかどうかを確認します。次に、2と3で割り切れるかどうかを示すことができるので、最初に6を確認できます。 3と6で割り切れることを意味します。すべての数字が素数であるならば、あなたはただ単に暗示することはできません。つまり、コードはすべてを個別にチェックする必要があります。

1つの肯定的な副作用は、(すべて明示的なので)あなたのコードであなたの意図を容易に読むことができるということです。この上

私の2セント...

1

あなたは、複数のスイッチを作成することができます。

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文を追加しました。ブール型switch文が後で来るかもしれません。

+0

There'sブール型の 'switch'を指しているのではなく、単に' if'/'else'です。 – Kevin

+0

ブール型スイッチとは、 'switch(i)' [...] 'case(i%10 == 3):instructions' [...]' case(i/10 == 5):instructions'です。それはスイッチの目的ではなく、それは多くの時間を節約するでしょう。 – DeadlyJesus

+1

ああ、そうです。しかし、問題は 'i%10 == 3 'と' i/10 == 5'(つまり53)の場合、両方とも印刷したいと思っていますが、 'switch'は1つしか打つことはないでしょう。最初。 – Kevin

7

私はコードを含む答えを書くようになりましたが、多くの人が私にそれを打ちました。私が言いたいことは、あなたが言及しているこの特定のコードメトリックがcyclomatic complexityと呼ばれ、恐ろしく悪いことではないということです。

要するに、メソッドが実行されたときにメソッドが取ることができる異なるパスの数を指します。ポストされたコードではかなり高いうちに、それを減らすためのヒント/解決策がたくさんあります個人的に私はそれが現在の形であっても、コードは非常に読みやすいと主張します - これはボーナスです。これは、かなりの量を削減し、まだ読めることが、私のポイントは、そのようなメトリックがすべてではない、時にはより読みだからif文がたくさんあるが簡単にできることであることができる - と可読性がミスをする可能性を低下させます、および

ああをはるかに簡単にデバッグになり、私はこの最後のセクション代わる:代替文のいずれかが呼ばれるたびにreplaced = trueようなブール値のフラグを使用することにより

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

を、上記の文はに崩れます:

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

+1条件付き複雑さの主題に関する先の研究を参照する。 – LarsH

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

+1

より高い評価の答えに近いように見えますが、 "THREE"、 "FIVE" ...の必要性を理解しているかどうかわかりません...あなたはある時点でそれらの数字の意味を更新しなければならないと思いますか? – WernerCD

+0

@WernerCD :-)はい。あなたは正しいです。これらの値を直接渡すことができます。あなたの思考を上記に含めることで、私の答えはOPのためのさらに別の解決策になります。 – AmitG

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

} 
+2

+1私は列挙型アプローチが好きですが、入れ子になった条件演算子には本当に立つことができません。しかし、これは個人的な好みかもしれません。条件付き演算子を入れ子にすることは決して私の経験則ではありません。 – helpermethod

+0

@helpermethod - 私はあなたの好みを理解することができます - それは非常に自然な感じのCの背景から来ています。 'Algol'にはループの短縮形と' case'文もありました。 – OldCurmudgeon

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

@ ugorenですので固定されています。 ''私のiPhoneにそのコードを入力しました。 ' ' – Bohemian

+0

ほとんどの場合、' j <= 7'です。 – ugoren

+0

@ugoren yup .... – Bohemian

7

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

信条は「if文なくす」これを達成するための一般的な考えですが、それは文脈に大きく依存します。

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

+1

あなたは - 「プログラムすることが難しい場合は、理解するのが難しいはずです」とサブスクライブします。 ;-)ここで質問と応答で囲まれているサンプルコードでは、変数と定数に意味のある名前がなく、関数と目的を少しはっきりさせることができます。 – Rawheiser

関連する問題