【问题标题】:Java 3D array: Storing cube, retrieving slice of cubeJava 3D数组:存储立方体,检索立方体切片
【发布时间】:2013-04-06 04:53:15
【问题描述】:

当使用一个奇数的立方 3d 数组(3x3x3、5x5x5、7x7x7 等)时,在给定切片方向的轴和一个值的情况下,返回该数组的 2d 切片的最有效方法是什么用于确定切片沿该轴的相关位置?

【问题讨论】:

  • 您能否更具体地说明“轴”和“切片”的含义?轴是否与 x-y-z 方向对齐?如果不是,如果您的横截面不是矩形,您希望返回什么?
  • 是的,轴将是一个 int 0/1/2,它对应于位于原始数组中间的 x/y/z 轴,那么该值可以从中心 0/+1/-1/etc 或从侧面偏移。在这种情况下,切片将是一个垂直于指定轴并按值偏移的二维数组。

标签: java multidimensional-array slice


【解决方案1】:

由于这对我来说是一个非常有趣的话题,所以我也一直在寻找答案。我认为您可能会幸运地使用Mark Byers 的方法:

Mark 没有将其存储在 3D 数组中,而是在如何使用 1D 数组方面提供了一种非常好的方法。

经过一番尝试,我想出了完整的立方体,希望它适合你:

public class Cube {
    int w, h, d;
    int[] cube;

    public Cube(int w, int h, int d) {
        this.w = w;
        this.h = h;
        this.d = d;
        System.out.println("cube: w" + w + ", h" + h + ", d" + d + " = " + (w * h * d));
        cube = new int[w * h * d];
    }

    int getCubeValue(int x, int y, int z) {
        return cube[x * h * d + y * d + z];
    }

    void setCubeValue(int x, int y, int z, int value) {
        System.out.println("value " + (x * h * d + y * d + z) + ": x" + x + ", y" + y + ", z" + z + " = " + value);
        cube[x * h * d + y * d + z] = value;
    }

    int[] xSlice(int x) {
        int[] slice = new int[h * d];
        for(int y = 0; y < h; y++) {
                for(int z = 0; z < d; z++) {
                        slice[y * d + z] = getCubeValue(x, y, z);
                }
        }
        return slice;
    }

    int xSliceValue(int[] slice, int y, int z) {
        return slice[y * d + z];
    }

    int[] ySlice(int y) {
        int[] slice = new int[d * w];
        for(int z = 0; z < d; z++) {
                for(int x = 0; x < w; x++) {
                        slice[z * w + x] = getCubeValue(x, y, z);
                }
        }
        return slice;
    }

    int ySliceValue(int[] slice, int x, int z) {
        return slice[z * w + x];
    }

    int[] zSlice(int z) {
        int[] slice = new int[w * h];
        for(int x = 0; x < w; x++) {
            for(int y = 0; y < h; y++) {
                slice[x * h + y] = getCubeValue(x, y, z);
            }
        }
        return slice;
    }

    int zSliceValue(int[] slice, int x, int y) {
        return slice[x * h + y];
    }
}

假设你制作了一个像 new Cube(3, 3, 3) 这样的 Cube,cube.getCubeValue(2, 2, 2) 可以接近最后一个值,因为它从零开始。

【讨论】:

    【解决方案2】:

    我认为您可以选择三个选项,具体取决于您希望切片方法的输入和输出是什么:

    • 对原始多维 Java 数组进行切片,生成原始多维 Java 数组,例如:

    int[][] ArrayUtils.slice(int[][][] cube, int axis, int sliceIndex)

    • 切片适用于原始多维 Java 数组,生成带有 getter 的对象,例如:

    SomeKindOf2DimArrayClass ArrayUtils.slice(int[][][] cube, int axis, int sliceIndex)

    • 切片使用非原始数组作为输入和输出,是这样一个类的方法:

    SomeKindOf2DimArrayClass slice(int axis, int sliceIndex)

    就您的界面而言。

    在实现方面,如果您使用原始数组,那么您别无选择,只能做一些“繁重的工作”——为 siice 构建一个二维数组——至少为第 3 轴。对于第一个轴,您只需使用一个二维数组(即result = Arrays.copyOf(cube[sliceIndex]),或者如果您感觉活泼,甚至可以使用参考);对于第二个轴,您将拥有类似

    for(int i=0; i<cube.length; i++) {
        myAllocated2dArray[i] = Arrays.copyOf(cube[i][sliceindex])
    }
    

    如果你使用的是一个对象,你有很多选择,从我刚刚描述的到@Aquillo 在his answer 这里的建议,再到使用 getter 方法的原始数组的 O(1) 空间包装器.

    您可能会通过阅读C language FAQs 中有关类似问题的答案来获得关于已经建议的两种实现的一些灵感,其中明确使用指针(引用):

    How can I use statically- and dynamically-allocated multidimensional arrays interchangeably when passing them to functions?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-05
      • 2016-07-08
      • 2021-08-04
      相关资源
      最近更新 更多