Обобщение цикла for в Java - PullRequest
       14

Обобщение цикла for в Java

5 голосов
/ 02 сентября 2011

Я не знаю, как описать мою проблему, поэтому я просто покажу пример кода:

int[][][] mat;
int n;
int specificValue;

for (int i = 0; i < n; i++) {
    if(mat[i][n-i][3] != specificValue) {
        doStuff();
    }
}

Я ищу целочисленные значения в 3d-массиве. Для каждого поля я должен использовать один из них:

  • счетчик, работающий от нуля до n
  • счетчик, работающий от n до нуля
  • фиксированное значение

Итак, я попытался создать метод, который спас бы меня от написания этого цикла for примерно 20 раз, но я потерпел неудачу, поэтому мне нужна помощь. Моя идея была примерно такой:

search(Loop.UP, Loop.DOWN, Loop.FIXED);

где "Loop" будет перечислением, представляющим одну из моих возможностей, но я не знаю, как реализовать это или если это возможно даже в Java без жесткого кодирования всех возможных комбинаций.

Надеюсь, вы можете помочь:)


ОК, более конкретно ... с моей настройкой я рисую вектор через этот 3d-массив, диагональ, чтобы быть конкретной, и я хочу знать, какие значения есть на этом векторе и только на этот вектор.

И поскольку существует более одной возможности нарисовать такой вектор, я бы хотел иметь более общий метод для получения значений. Мой поиск может быть таким простым, как

search(Loop.UP, Loop.FIXED, Loop.FIXED);   // one plane

, который будет простым циклом for с одним счетчиком, но также

search(Loop.DOWN, Loop.UP, Loop.UP);   // through all three planes

Ответы [ 3 ]

5 голосов
/ 02 сентября 2011
Path pathX = new Path.Up();
Path pathY = new Path.Down(n);
Path pathZ = new Path.Fixed(3);

for (int i = 0; i < n; i++) {
    if(mat[pathX.pos(i)][pathY.pos(i)][pathZ.pos(i)] != specificValue) {
        doStuff();  
    }
}

где

public interface Path {
    public int pos(int i);

    public static class Up implements Path {
         @Override public int pos(int i) { return i; }
    }

    public static class Down implements Path {
         private int n;
         public Down(int n) { this.n = n; }
         @Override public int pos(int i) { return n - i - 1; }
    }

    public static class Fixed implements Path {
         private int v;
         public Down(int v) { this.v = v; }
         @Override public int pos(int i) { return v; }
    }

Я не использовал Enum, потому что Down зависит от n и Fixed от некоторого значения.

1 голос
/ 02 сентября 2011

Лучшее, что я могу себе представить на данный момент, это:

static final int UP = -2, DOWN = -1;

static void loop1(int[][][] A, int t1, int t2, int t3) {
    switch (t1) {
    case UP:
        for (int i = 0; i < A.length; i++)
            loop2(A[i], t2, t3);
        break;
    case DOWN:
        for (int i = A.length - 1; i >= 0; i--)
            loop2(A[i], t2, t3);
        break;
    default:
        loop2(A[t1], t2, t3);
    }
}

static void loop2(int[][] A, int t2, int t3) {
    switch (t2) {
    case UP:
        for (int i = 0; i < A.length; i++)
            loop3(A[i], t3);
        break;
    case DOWN:
        for (int i = A.length - 1; i >= 0; i--)
            loop3(A[i], t3);
        break;
    default:
        loop3(A[t2], t3);
    }
}

static void loop3(int[] A, int t3) {
    switch (t3) {
    case UP:
        for (int i = 0; i < A.length; i++) {
            // Do something with A[i] here, such as...
            System.out.println(A[i]);
        }
        break;
    case DOWN:
        for (int i = A.length - 1; i >= 0; i--) {
            // Do something with A[i] here, such as...
            System.out.println(A[i]);
        }
        break;
    default:
        // Do something with A[t3], such as...
        System.out.println(A[t3]);
    }
}

FIXED - единственная опция, для которой требуется индекс, и, следовательно, кодируется как индекс. UP и DOWN не являются индексами, поэтому они кодируются с использованием отрицательных чисел. Использование будет что-то вроде

public static void main(String[] args) {
    int[][][] m = { { { 1, 2 }, { 3, 4 } }, { { 5, 6 }, { 7, 8 } } };
    loop1(m, DOWN, 1, UP);
}

В моем примере System.out.println результат будет

7
8
3
4
1 голос
/ 02 сентября 2011

Вы можете использовать список индексов. В Python это может выглядеть примерно так:

LOOP_UP = 20
LOOP_DOWN = LOOP_UP + 20
LOOP_FIXED = LOOP_DOWN + 20

def indexesOfLoopType(loopType, val):
    if loopType == LOOP_UP:
        return range(val)    
    if loopType == LOOP_DOWN:
        return range(val, 0)
    return [val] * val # make a list [val, val, val... ] of length val

def search(loopFirstIndex, loopSecondIndex, loopThirdIndex):
    # use indexesOfLoopType() to get lists of indexes
    # use those lists to iterate over mat
...