【问题标题】:Getting all posssible array index positions in an efficient way以有效的方式获取所有可能的数组索引位置
【发布时间】:2016-07-08 06:18:32
【问题描述】:

您好,我想找到一种方法来查找任意大小和任意数量的维度大小数组中的所有可能索引位置。例如:

int [][][] myArray = new int [2][3][2]

然后我会想要所有可能的数组索引位置,所以输出会是这样的:

0,0,0
1,0,0
0,1,0
0,2,0

以此类推,基本上是数组的所有位置,并且这种方式比嵌入大量循环更有效。

【问题讨论】:

  • 您已经定义了一个 3 维数组,并且正在显示一个 2 维数组。它比你想表达的更微妙。但是,您真的需要显示所有位置,还是需要枚举所有可能的索引组合?
  • 您希望输入是什么?维度序列(2、3、2)还是实际数组本身?
  • @Makoto 很抱歉,如果输出应该是这样的,那么这并没有显示数组应该是什么样子,它只是显示了所有可能的索引组合。我只是没有把它们都展示出来,因为它会很多。但输出我只需要可能的索引组合。
  • @PaulBoddington 嗨,如果输出部分令人困惑,我只需要任意数组的所有可能索引组合,抱歉
  • 我不明白如果没有 某种形式的嵌套迭代,您将如何完成此操作。你可以把它抽象出来,让它看起来好像只有一两个循环发生,但不管你有多少维度,你都会循环。

标签: java arrays performance indexing


【解决方案1】:

多维数组是语法糖,它们物理上位于一维内存中:

所以,你可以试试这样的:

final int dim1 = 2;
final int dim2 = 3;
final int dim3 = 4;
final int[][][] myArray = new int[dim1][dim2][dim3];

for (long i = 0; i < ((long) dim1 * dim2 * dim3); i++) {
    long idx = i;
    final int i3 = (int) (idx % dim3);
    idx /= dim3;
    final int i2 = (int) (idx % dim2);
    idx /= dim2;
    final int i1 = (int) idx;
    System.out.println(i1 + "," + i2 + "," + i3);
}

注意:此代码使用 %/ 运算符,它们非常慢,但如果您的尺寸是 2 的幂,您可以将其替换为 &amp;&gt;&gt;&gt; ,它们运行速度更快,嵌套循环也没有

另一种变体:

final int dim1 = 2;
final int dim2 = 3;
final int dim3 = 4;
final int[][][] myArray = new int[dim1][dim2][dim3];

int i1 = 0;
int i2 = 0;
int i3 = 0;
for (long i = 0; i < ((long) dim1 * dim2 * dim3); i++) {
    System.out.println(i1 + "," + i2 + "," + i3);
    i3++;
    if (i3 == dim3) {
        i3 = 0;
        i2++;
        if (i2 == dim2) {
            i2 = 0;
            i1++;
        }
    }
}

它可以工作得更快,但它在循环内有分支,因此最好对这两种变体进行基准测试

【讨论】:

    【解决方案2】:

    我喜欢这样的方法。像这样使用 List 的自定义实现的好处是,您可以表示所有可能的索引组合,而不必同时将它们全部存储在内存中。

    public static void main(String[] args) {
        List<List<Integer>> indices = indices(2, 3);
        for (List<Integer> list : indices)
            System.out.println(list);
    }
    
    public static List<List<Integer>> indices(final int... dimensions) {
        int s = 1;
        for (int a : dimensions)
           s *= a;
        final int size = s;
        return new AbstractList<List<Integer>>() {
            @Override
            public int size() {
                return size;
            }
            @Override
            public List<Integer> get(int index) {
                if (index < 0 || index >= size)
                    throw new IndexOutOfBoundsException();
                List<Integer> temp = new ArrayList<>();
                for (int d : dimensions) {
                    temp.add(index % d);
                    index /= d;
                }
                return Collections.unmodifiableList(temp);
            }
        };
    }
    

    【讨论】:

      猜你喜欢
      • 2019-05-20
      • 1970-01-01
      • 2013-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-09
      相关资源
      最近更新 更多