2016-08-20 12 views
0

コーディングクラスを取ってから約20年経ちました。私は時々楽しみのためにそれをもう一度拾うが、私のコードは曖昧で&は非効率的である。Javaでforeachループのネストを避ける

私はちょうど400以上の要素を持つ配列を持っています。私は現在、配列上で動作するネストされたforeachループを持っています。

import acm.program.ConsoleProgram; 
import java.awt.Color; 
import acm.io.IODialog; 
import java.text.*; 
import static java.lang.Math.*; 
import java.util.*; 

/** Tests to see if user color matches sample colors */ 

public class test extends ConsoleProgram 

{ 

    //defining sample colors 

    Color[] dmc = 
    { 
     new Color(255,255,255), 
     new Color(148,91,128), 
     new Color(206,148,186), 
     new Color(236,207,225), 
     new Color(243,218,228), 

    }; 

public void run() 
{ 
    average(); 

} 

//averages three colors, then tests for match to given color 

public void average() 
{ 

    //asks for user color 
    IODialog dialog = new IODialog(); 
    int stitchRed= dialog.readInt("Enter red value: "); 
    int stitchGreen= dialog.readInt("Enter green value: "); 
    int stitchBlue= dialog.readInt("Enter blue value: "); 
    Color stitchColor= new Color(stitchRed,stitchGreen,stitchBlue); 

    //gets averages for dmc colors 
    for (Color i:dmc) 
    { 
     for (Color j:dmc) 
     { 
      for (Color k:dmc) 
      { 
       int indexI = Arrays.asList(dmc).indexOf(i); 
       int indexJ = Arrays.asList(dmc).indexOf(j); 
       int indexK = Arrays.asList(dmc).indexOf(k); 
       if(indexI <= indexJ && indexJ <= indexK) 
       { 
       int iRed = i.getRed(); 
       int jRed = j.getRed(); 
       int kRed = k.getRed(); 
       int iGreen = i.getGreen(); 
       int jGreen = j.getGreen(); 
       int kGreen = k.getGreen(); 
       int iBlue = i.getBlue(); 
       int jBlue = j.getBlue(); 
       int kBlue = k.getBlue(); 
       int redAverage = (iRed+jRed+kRed)/3; 
       int greenAverage = (iGreen+jGreen+kGreen)/3; 
       int blueAverage = (iBlue+jBlue+kBlue)/3; 
       Color colorAverage = new Color(redAverage,greenAverage,blueAverage); 

       //tests to see if any thread average equals user color 
       if (colorAverage.equals(stitchColor)) 
       { 
        println("The color match is: " + i + ", " + j + ", " + k); 
       } 
      } 
     } 
     } 
    } 

    println("no more matches"); 
    } 
} 

これはうまくコンパイルされますが、非常に遅く実行されます。

これを行うより効率的な方法はありますか?
おそらくネストの周りを取得する方法 - の効果に何か:(:DMC色i、j、k)は、

ため

+2

あなたの期待は何ですか?あなたのコードで何をしようとしていますか? –

+0

あなたのユースケースによっては、それはすぐに本当に実行できるように、このコードは、並列化かもしれませんが、あなたが達成したいものについての詳細を教えする必要があります。 –

+0

あなたは最初にあなたの配列をArrayListに変換する、2:最初の2つの項目が等しいかどうかをチェックすることで、速度を1で得ることができます。 (あなたのコードに基づいて彼らがなぜ迷惑を掛けないかをチェックしてください)、あなたは何ミリ秒も節約することができます。 :) – Elltz

答えて

0

if文で多くの組み合わせを除外することを考慮すると、for-eachループの代わりに実際に処理したい要素を反復するだけのfor-loopsを使用するのが最適です。例えば。 i < = jは、iでjで反復を開始できることを意味します。

コメントに記載されているように、今後の改善が可能かもしれません。

0

あなたはjava.lang.Objectの中で定義されたequalsメソッドを試すことができ、

for(x=1;x<401;x++) 
{ 
    Color j= dmc[x]; 
    Color k= dmc[x+1]; 
    int indexI = Arrays.asList(dmc).indexOf(i); 
    int indexJ = Arrays.asList(dmc).indexOf(j); 
    int indexK = Arrays.asList(dmc).indexOf(k); 
    if(indexI <= indexJ && indexJ <= indexK) 
    { 
     //bunch of code... 

ような何かをしようとか、することができます。これが役立つことを願っています。

+0

私は、i、j、kがすべて同じ値であることを可能にする必要があります。そうでない場合でも、配列の3つの要素、つまり隣接する要素である必要があります。私はもともとインデックス条件をオフにしていましたが、順列について言及しない方が効率的だったようです。私はすでに色a、b、cが動作すれば色c、b、aも動作することを知っています。 –

+0

3つの要素を選択してお互いにチェックしたいのですか、配列内の他のすべての要素と1つ1つずつチェックしますか? –

+0

3つ。プログラムは、ユーザーに(作成しようとしている)色を促すことから始まります。配列は、製造者によって提供された刺繍糸の色のリストである。アイデアは、単純な平均を使用して、提供されたスレッドカラーの3つを混合することからユーザーカラーを作成することが可能かどうかを調べることです。 –

1

(それはSSCCEないので、私がテストしたコードをデバッグすることはできませんので、すべてのエラーのためにI appologies)
詳細についてはコメントを参照してください、次のことを考えてみます。

Color[ ] dmc = {element1, element2, ...}; 

for(int i =0; i < dmc.length ; i++) 
{ 

    //iterate only on values >= i 
    for(int j = i; j< dmc.length; j++) 
    { 
     //loop only on values >= j 
     for(int k = j; k < dmc.length ; k++) 
     { 

      //not needed, you already have i, j, k 
      //int indexI = Arrays.asList(dmc).indexOf(i); 
      //int indexJ = Arrays.asList(dmc).indexOf(j); 
      //int indexK = Arrays.asList(dmc).indexOf(k); 


      //condition is not needed. Allways true. 
      //if(indexI <= indexJ && indexJ <= indexK) { } 

      //bunch of code... 

EDIT:短いデモをプリントアウトするための唯一の希望の発生率:

 public static void main(String[] args) { 

      Color[ ] dmc = {Color.AQUA, Color.AZURE, Color.BEIGE, Color.BLACK, Color.BLUE, 
        Color.BROWN, Color.CHOCOLATE, Color.CYAN, Color.CRIMSON, Color.FUCHSIA}; 

      for(int i =0; i < dmc.length ; i++) 
      { 

       System.out.printf("\n >>>>>> i= %s", i); 
       //iterate only on values >= i 
       for(int j = i; j< dmc.length; j++) 
       { 
        System.out.printf("\n   j= %s",j); 

        //loop only on values >= j 
        for(int k = j; k < dmc.length ; k++) 
        { 

        System.out.printf("\n   k= %s",k); 
        } 
       } 
      } 

     } 

EDIT II:後はMCVEは、私はそれを修正投稿しましたfastEverage()メソッドを追加します。これは、反復回数の少ないeverage()と同じ計算を行う必要があります。私がチェック色の単一セットに
、どちらの方法でも同じ出力を有する:

import java.awt.Color; 
import java.util.Arrays; 

/** Tests to see if user color matches sample colors */ 
public class Test 

{ 

    //defining sample colors 

    Color[] dmc = 
     { 
       new Color(255,255,255), 
       new Color(148,91,128), 
       new Color(206,148,186), 
       new Color(236,207,225), 
       new Color(243,218,228), 

     }; 

    //averages three colors, then tests for match to given color 
    public void average() 
    { 

     //asks for user color 
     int stitchRed = 203; 
     int stitchGreen= 164; 
     int stitchBlue= 189; 

     Color stitchColor= new Color(stitchRed,stitchGreen,stitchBlue); 

     //gets averages for dmc colors 
     for (Color i:dmc) 
     { 
      for (Color j:dmc) 
      { 
       for (Color k:dmc) 
       { 
        int indexI = Arrays.asList(dmc).indexOf(i); 
        int indexJ = Arrays.asList(dmc).indexOf(j); 
        int indexK = Arrays.asList(dmc).indexOf(k); 
        if((indexI <= indexJ) && (indexJ <= indexK)) 
        { 
         int iRed = i.getRed(); 
         int jRed = j.getRed(); 
         int kRed = k.getRed(); 
         int iGreen = i.getGreen(); 
         int kGreen = k.getGreen(); 
         int jGreen = j.getGreen(); 
         int iBlue = i.getBlue(); 
         int jBlue = j.getBlue(); 
         int kBlue = k.getBlue(); 
         int redAverage = (iRed+jRed+kRed)/3; 
         int greenAverage = (iGreen+ jGreen + kGreen)/3; 
         int blueAverage = (iBlue+jBlue+kBlue)/3; 

         Color colorAverage = new Color(redAverage,greenAverage,blueAverage); 

         //tests to see if any thread average equals user color 
         if (colorAverage.equals(stitchColor)) 
         { 
          System.out.println("The color match is: " + i + ", " + j + ", " + k); 
         } 

        } 
       } 
      } 
     } 

     System.out.println("no more matches"); 
    } 

    //averages three colors, then tests for match to given color 
    public void fastEverage() 
    { 

     //asks for user color 
     int stitchRed = 203; 
     int stitchGreen= 164; 
     int stitchBlue= 189; 

     Color stitchColor= new Color(stitchRed,stitchGreen,stitchBlue); 

     Color colorI, colorJ, colorK; 

     for(int i =0; i < dmc.length ; i++) 
     { 

      colorI = dmc[i]; 

      //iterate only on values >= i 
      for(int j = i; j< dmc.length; j++) 
      { 

       colorJ = dmc[j]; 

       //loop only on values >= j 
       for(int k = j; k < dmc.length ; k++) 
       { 

        colorK = dmc[k]; 

        int iRed = colorI.getRed(); 
        int jRed = colorJ.getRed(); 
        int kRed = colorK.getRed(); 
        int iGreen = colorI.getGreen(); 
        int kGreen = colorK.getGreen(); 
        int jGreen = colorJ.getGreen(); 
        int iBlue = colorI.getBlue(); 
        int jBlue = colorJ.getBlue(); 
        int kBlue = colorK.getBlue(); 
        int redAverage = (iRed+jRed+kRed)/3; 
        int greenAverage = (iGreen+ jGreen + kGreen)/3; 
        int blueAverage = (iBlue+jBlue+kBlue)/3; 

        Color colorAverage = new Color(redAverage,greenAverage,blueAverage); 

        //tests to see if any thread average equals user color 
        if (colorAverage.equals(stitchColor)) 
        { 
         System.out.println("The color match is: " + colorI + ", " + colorJ + ", " + colorK); 
        } 

       } 
      } 
     } 

     System.out.println("no more matches"); 
    } 

    public static void main(String[] args) 
    { 
     new Test().average(); 
     new Test().fastEverage(); 

    } 
} 

2つの方法の間の実行時間の差は、このテストケースで、重要である:

ランタイムナノ秒everage()ナノ秒fastEverage()の84752814

実行時の76497255

+0

私はこれで始まりましたが、コンパイルできませんでした。 –

+1

なぜですか? [MCVE]を投稿すると、理由がわかります。 – c0der

+0

私はコーディングクラスを取ってから20年経ちました。私のコードは非常に長くて扱いにくいです - 約600行とそれに別の部分はありません - この関数だけです(よく、2つはマッチしますが、マッチに最も近いものは2つです)。 Minimalは本当にこのFrankensteinコードのオプションではありません。私のコードを整理することができる他の場所がありますが、いくつかのテストをした後で、これは私のプロセッサを掛けているステップです。私のプログラミングソフトウェアがインターネットに接続しない別のラップトップにあるという事実もまた複雑です。私はすべてを再入力しています。 –

1

それは@ C0derの答えと同じですが、ちょうど質問のvarに同じ名前を使用しています。

for (int indexI = 0; indexI < dmc.length; indexI++) { 
     Color i = dmc[indexI]; 
     for (int indexJ = indexI; indexJ< dmc.length; indexJ++) { 
      Color j = dmc[indexJ]; 
      for (int indexK = indexJ; indexK< dmc.length; indexK++) { 
       Color k = dmc[indexK]; 
       //.... 
      } 
     } 
    } 

EDITED:

public void average() { 
    //asks for user color 
    IODialog dialog = new IODialog(); 
    int stitchRed = dialog.readInt("Enter red value: "); 
    int stitchGreen = dialog.readInt("Enter green value: "); 
    int stitchBlue = dialog.readInt("Enter blue value: "); 
    Color stitchColor = new Color(stitchRed, stitchGreen, stitchBlue); 
    for (int indexI = 0; indexI < dmc.length; indexI++) { 
     Color i = dmc[indexI]; 
     for (int indexJ = indexI; indexJ < dmc.length; indexJ++) { 
      Color j = dmc[indexJ]; 
      for (int indexK = indexJ; indexK < dmc.length; indexK++) { 
       Color k = dmc[indexK]; 
       int iRed = i.getRed(); 
       int jRed = j.getRed(); 
       int kRed = k.getRed(); 
       int iGreen = i.getGreen(); 
       int jGreen = j.getGreen(); 
       int kGreen = k.getGreen(); 
       int iBlue = i.getBlue(); 
       int jBlue = j.getBlue(); 
       int kBlue = k.getBlue(); 
       int redAverage = (iRed + jRed + kRed)/3; 
       int greenAverage = (iGreen + jGreen + kGreen)/3; 
       int blueAverage = (iBlue + jBlue + kBlue)/3; 
       Color colorAverage = new Color(redAverage, greenAverage, blueAverage); 
       //tests to see if any thread average equals user color 
       if (colorAverage.equals(stitchColor)) { 
        System.out.println("The color match is: " + i + ", " + j + ", " + k); 
       } 
      } 
     } 
    } 

    System.out.println("no more matches"); 
} 
+0

ありがとう、これはこの方法ではるかに明確です。 +1 – c0der

0

ジャストアイデア。検索を分割することができます。最初の検索で一致するものを見つける可能性があります。そうであれば、残りの部分を検索する必要はありません。一致していない場合は、前方に移動して一致するものを検索することができます。

int i,j,k;  
for(i=0;i<100;i++){ 
    for(j=i;j<100;j++){ 
     for(k=j;k<100;k++){ 
     //..do stuffs.....// 
     } 
    } 
} 
if(matchnotfound){ 
    for(i=100;i<200;i++){ 
    for(j=i;j<200;j++){ 
     for(k=j;k<200;k++){ 
     //..do stuffs.....// 
     } 
    } 
    } 
} 
if(matchnotfound){ 
    for(i=200;i<300;i++){ 
    for(j=i;j<300;j++){ 
     for(k=j;k<300;k++){ 
     //..do stuffs.....// 
     } 
    } 
    } 
} 
if(matchnotfound){ 
    for(i=300;i<400;i++){ 
    for(j=i;j<400;j++){ 
     for(k=j;k<400;k++){ 
     //..do stuffs.....// 
     } 
    } 
    } 
} 
関連する問題