2016-08-20 199 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.....// 
     } 
    } 
    } 
}