【问题标题】:Generalizing a for-loop in Java泛化 Java 中的 for 循环
【发布时间】:2011-11-08 20:20:05
【问题描述】:

我真的不知道如何描述我的问题,所以我只展示一个代码示例:

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

其中“循环”将是一个枚举,代表我的一种可能性,但我不知道如何实现它,或者这在 Java 中是否可以实现,而无需对所有可能的组合进行硬编码。

希望你能帮忙:)


好的,更具体...通过我的设置,我正在通过这个 3d 数组绘制一个向量,具体来说是一个对角线,我想知道这个向量上的值是什么,并且 在这个向量上。

而且由于绘制这样一个向量的可能性不止一种,我希望有一种更通用的方法来获取这些值。我的搜索可以很简单

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

这将是一个带有一个计数器的简单 for 循环,但也是

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

【问题讨论】:

  • 您能更具体地说明您想要什么吗?您希望能够在运行时而不是编译时为每个字段指定使用哪种类型的索引?
  • 您可以只拥有 (UP, DOWN) 和 (DOWN, UP) 或全部四种组合吗?还有多少个固定值?
  • 您能否提供更多示例,说明此代码 sn-p 在“20 次”中可能如何变化?如果它总是以某种方式涉及 n,i,specificValue,你可以省略 Loop.FIXED,并用 specificValue 替换它,你可以传入一个 `int[] counter1 = new int[] { value1, value2 } - 然后在您的函数体中,您可以检查 value1 value2 是否隐式确定它是 Loop.UP 还是 Loop.DOWN。
  • 正确的方法是实现你自己的Iterator‌​。这仅在doStuff 不修改比较的值时才有效。是吗?
  • doStuff() 不执行与此代码 sn-p 一致的任何操作

标签: java multidimensional-array for-loop


【解决方案1】:

您可以使用索引列表。在 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

【讨论】:

  • 嗯,不错的主意,但是创建一个升序整数列表只是为了迭代另一个列表对我来说似乎很令人毛骨悚然。
【解决方案2】:

目前我能想到的最好的是:

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 是唯一需要索引的选项,因此被编码为索引。 UPDOWN 不是索引,因此它们使用负数编码。用法会像

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

【讨论】:

  • 你能解释的更详细一点吗?我真的不明白这些功能应该做什么。
  • 嗯,我认为这行不通。我同时需要每个步骤的结果值,所以我可以立即在矩阵中进行查找。无论如何,此任务将非常频繁地执行,因此必须非常快。我想我只需要对其进行硬编码......但非常感谢您的努力!
【解决方案3】:
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 依赖于 nFixed 的某个值。

【讨论】:

  • @Klamann 我做了一个编辑:(n - i) -> (n - i - 1) 否则你会得到 ArrayIndexOutOfBoundException。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
  • 2016-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多