有没有更好的方法来实现这些嵌套循环?

时间:2013-08-03 01:28:31

标签: java loops for-loop

假设有三个数组:

char [] one = {'a','b','c'};
char [] two = {'1','2','3'};
char [] three = {'x','y','z'};

如果我想像这样打印它们:

a 1 x
a 1 y
a 1 z

a 2 x
a 2 y
.....
c 3 z

我必须创建三个嵌套循环;

for(char i : one)
  for(char j : two)
    for(char k : three)
       //.....

假设我有7个数组,它将是7个嵌套循环。

有没有更好的方法可以做到这一点或API?我知道你可能会问你为什么这么做,这只是思考的问题。

5 个答案:

答案 0 :(得分:5)

诀窍是使用一系列索引。更新它们就像汽车中的里程表:最不重要的索引然后如果溢出设置为零并继续下一个...当没有溢出时,更新完成。继续打印。当最后一个索引溢出时,打印完成。

// Accept an array of character arrays and print a nest
// of their contents.
static void print(char [] [] a) {
    int n_arrays = a.length;
    int [] indices = new int[n_arrays];  // All set to 0 by java
    // Decrement so that first increment is to all zeros. Avoids test for empty arrays.
    indices[n_arrays - 1] = -1; 
    for (int j = 0;;) {
        // Increment indices.
        for (j = n_arrays - 1; j >= 0; j--) {
            if (++indices[j] >= a[j].length) {
                indices[j] = 0;
            }
            else {
                break;  // No overflow. Increment is complete.
            }
        }
        if (j < 0) {
            break; // Last index overflowed.  We're done.
        }
        // Print.
        for (int i = 0; i < n_arrays; i++) {
            System.out.print(a[i][indices[i]]);
        }
        System.out.println();
    }
}

// Varargs version.
static void printArgs(char [] ... a) {
    print(a);
}

static char [] one = {'a','b','c'};
static char [] two = {'1','2','3'};
static char [] three = {'x','y','z'};

public static void main(String[] a) {
    print(new char [] [] { one, two, three } );
    printArgs(one, two, three);
}

答案 1 :(得分:4)

这是一种基于维护显式索引数组的方法(没有递归或嵌套循环):

static boolean incrementIndices(char[][] arrs, int[] inds) {
    int n = arrs.length;
    for(int i = n-1; i >= 0; i--) {
        if(inds[i] < arrs[i].length-1) {
            inds[i]++;
            return true;
        }
        inds[i] = 0;
    }
    return false; // could not increment further
}

static void printIndices(char[][] arrs, int[] inds) {
    int n = arrs.length;
    for(int i=0; i<n; i++) {
        System.out.print(arrs[i][inds[i]]);
    }
    System.out.println();
}

public static final void main(String[] args) {
    char [] one = {'a','b','c'};
    char [] two = {'1','2','3'};
    char [] three = {'x','y','z'};

    char[][] arrs = {one, two, three};
    int[] inds = new int[3];

    do {
        printIndices(arrs, inds);
    } while(incrementIndices(arrs, inds));
}

输出:

a1x
a1y
a1z
a2x
a2y
a2z
a3x
a3y
a3z
b1x
b1y
b1z
b2x
b2y
b2z
b3x
b3y
b3z
c1x
c1y
c1z
c2x
c2y
c2z
c3x
c3y
c3z

答案 2 :(得分:3)

如果你真的不想创建嵌套循环,可以使用递归和变量。这是在参数末尾接受数组的方法

// StringBuilder will act like stack that will contain elements that need to
// be printed
public static void printArrays(int arrayIndex, StringBuilder sb, char[]... arrays){

    for (char c : arrays[arrayIndex]) {
        sb.append(c);//add character from current array to stack

        // if we have more arrays use this method again but this time 
        // on next array (by passing increased value of arrayIndex) 
        if (arrayIndex < arrays.length - 1)
            printArrays(arrayIndex + 1, sb, arrays);

        // if we don't have more arrays print current combination of letters 
        if (arrayIndex == arrays.length - 1)
            System.out.println(sb.toString());

        // we are here so we iterated via all arrays, and current character 
        // was already used so we can remove it safely 
        sb.deleteCharAt(sb.length() - 1);
    }
}

用法

char[] one = { 'a', 'b', 'c' };
char[] two = { '1', '2', '3' };
char[] three = { 'x', 'y', 'z' };
char[] four = {'!', '@', '#', '$'};

printArrays(0, new StringBuilder(), one, two, three, four);

答案 3 :(得分:3)

这是一个使用方便的varargs参数的递归解决方案,因此适用于任意数量的数组:

public static String combinations(String s, char[]... arrays) {
    if (arrays.length == 0) return s + "\n";
    String result = "";
    for (char c : arrays[0])
        result += combinations(s + c, Arrays.copyOfRange(arrays, 1, arrays.length));
    return result;
}

效率不高,但很简短。

您可以直接使用空白字符串调用它来启动,但公共包装函数可以创建更好的API:

public static String combinations(char[]... arrays) {
    return combinations("", arrays);
}

这是一些测试代码:

char[] one = { 'a', 'b', 'c' };
char[] two = { '1', '2', '3' };
char[] three = { 'x', 'y', 'z' };
char[] four = { 'm', 'n', 'o' };
System.out.println(combinations(one, two, three, four));

输出:

a1xm
a1xn
a1xo
a1ym
a1yn
a1yo
a1zm
a1zn
a1zo
a2xm
a2xn
a2xo
a2ym
a2yn
a2yo
a2zm
a2zn
a2zo
a3xm
a3xn
a3xo
a3ym
a3yn
a3yo
a3zm
a3zn
a3zo
b1xm
b1xn
b1xo
b1ym
b1yn
b1yo
b1zm
b1zn
b1zo
b2xm
b2xn
b2xo
b2ym
b2yn
b2yo
b2zm
b2zn
b2zo
b3xm
b3xn
b3xo
b3ym
b3yn
b3yo
b3zm
b3zn
b3zo
c1xm
c1xn
c1xo
c1ym
c1yn
c1yo
c1zm
c1zn
c1zo
c2xm
c2xn
c2xo
c2ym
c2yn
c2yo
c2zm
c2zn
c2zo
c3xm
c3xn
c3xo
c3ym
c3yn
c3yo
c3zm
c3zn
c3zo

答案 4 :(得分:2)

首先你需要合并所有数组

char[] one = {'a', 'b', 'c'};
char[] two = {'1', '2', '3'};
char[] three = {'x', 'y', 'z'};
char[] four = {'m', 'n', 'o'};
char[][] a = new char[4][];
a[0] = one;
a[1] = two;
a[2] = three;
a[3] = four;

然后你可以用这样的for打印你想要的东西

int[] index = new int[4];
for (int i = 0; i < Math.pow(3, 4); i++) {
    int current = i;
    for (int j = 0; j < 2; j++) {
        index[j] = current % 3;
        current /= 3;
    }
    int k=0;
    for (int j=index.length-1;j>=0;j--) {
        System.out.print(a[k][index[j]]+" ");
        k++;
    }
    System.out.println();
}