2016-08-20 253 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"); 
    } 
} 

這個編譯得很好,但真的很慢。

有沒有更有效的方法來做到這一點?
可能的方式來解決嵌套 - 東西的效果:

的(顏色I,J,K:DMC)

+2

你的期望是什麼?你想用你的代碼做什麼? –

+0

根據您的使用情況,此代碼可能是可並行化的,因此它可以很快運行,但您需要告訴我們更多關於您想實現的內容。 –

+0

你可以通過1得到一些速度:最初將你的數組轉換爲一個ArrayList,2:檢查前兩項是否相等。 (根據你的代碼,如果他們不檢查爲什麼打擾),你可以節省一些毫秒。 :) – Elltz

回答

0

考慮到你在if語句中過濾了很多組合,一個優化就是使用for循環遍歷實際上想要處理的元素而不是for-each-loops。例如。 i < = j表示您可以在i處開始j中的迭代。

取決於您在評論中所述的意圖,可能會進行進一步的改進。

0

你可以嘗試像

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... 

,或者你可以嘗試在等於定義java.lang.Object繼承的方法。希望這會有所幫助。

+0

我需要允許i,j和k都是相同的值。即使它們不是,我也需要它們是陣列中的任何三個元素,而不僅僅是相鄰的元素。我原本離開了索引條件,但似乎更有效的是不提及排列。我已經知道,如果顏色a,b和c起作用,那麼顏色c,b和a也將起作用。 –

+0

你想選擇任何三個元素,並相互檢查它們,或者你想檢查每個元素對數組中的所有其他元素一個接一個嗎? –

+0

任何三個。該程序通過提示用戶輸入一種顏色(他們正在嘗試創建)來開始。該陣列是由製造商提供的繡花線顏色列表。這個想法是通過使用簡單的方法來確定是否可以通過混合任何三種提供的線色創建用戶顏色。 –

1

(我不能測試和調試代碼,因爲它不是一個SSCCE,所以我對任何錯誤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... 

編輯:一個簡短的演示,只打印出想要的發病率:

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

     } 

編輯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行,沒有另一部分 - 只是這個函數(好吧,如果你把它計算爲>它們是否匹配,哪個匹配最接近)。對於這個Frankenstein代碼來說,最小並不是真正的選擇。有可能在其他地方我的代碼可以清理,但在做了一些測試後,這是掛斷我的處理器的一步。由於我的所有編程軟件都在另一臺筆記本電腦上,而這些筆記本電腦無法連接到互聯網,這也使事情變得複雜。我正在重新輸入一切。 –

1

它等於@ C0der的答案,只是對問題的變種使用相同的名稱。

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]; 
       //.... 
      } 
     } 
    } 

編輯:

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.....// 
     } 
    } 
    } 
}