【问题标题】:Set rank of array at runtime在运行时设置数组的等级
【发布时间】:2011-01-05 15:09:05
【问题描述】:

我想知道最简单的方法是实现一个在运行时指定排名的数组。

我正在处理的示例存储格点的布尔值数组,我希望用户能够选择模型在运行时使用多少空间维度。

我查看了 Array.newInstance() 方法:

dimensionOfSpace = userInputValue;  // this value comes from GUI or whatever
int latticeLength = 5;  // square lattice for simplicity

int[] dimensions = new int[dimensionOfSpace];
for(int i = 0; i < l.length; i++) l[i] = length; 
Object lattice = Array.newInstance(boolean.class, dimensions);

但是以任何方式访问这些值似乎都需要非常慢的方法,例如递归地使用 Array.get 直到返回的值不再是一个数组,即使用 isArray()。

我在这里错过了一个明显的解决方案吗?我希望能够以类似于 foo[i][j][k] 的方式访问这些值。

【问题讨论】:

  • 有些人会将您尝试做的事情称为“在运行时设置数组的等级”。很多人会认为您的意思是设置固定排名数组的大小。
  • @HamishGrubijan:我希望 HashMap 可以工作(使用坐标的字符串表示),但如果数据结构变大,效率会非常低。

标签: java arrays multidimensional-array


【解决方案1】:

看起来您正在寻找某种方式来声明数组在运行时有多少维。我不知道如何使用多维 ArrayList 或任何必须在编译时指定维度的多维结构来完成此操作。

我看到的唯一答案是使用一个简单的线性数组,该数组包含在一个类中,该类将多维坐标与其在底层数组中的位置相互转换。这基本上就是诸如 C 之类的语言通过使用一块连续的内存来存储多维数组的方式。

代码如下所示:

import java.util.*;

class MultiArray<T>{
    private int[] dimensions;
    private Object[] array;

    public MultiArray(int ... dimensions){
        this.dimensions=dimensions;
        //Utils.product returns the product of the ints in an array
        array=new Object[Utils.product(dimensions)];
    }

    public void set(T value, int ... coords){
        int pos=computePos(coords); 
        array[pos]=value;
    }

    public T get(int ... coords){
        int pos=computePos(coords);
        return (T)(array[pos]);
    }

    private int computePos(int[] coords){
        int pos=0;
        int factor=1;
        for (int i=0;i<coords.length;i++){
            pos+=factor*coords[i];
            factor*=dimensions[i];
        }
        return pos;
    }
}

class Main{
    public static void main(String args[]){
        MultiArray<Integer> m=new MultiArray<Integer>(new int[]{5,4,3}); 
        Random r=new Random();

        for(int i=0;i<5;i++)
            for(int j=0;j<4;j++)
                for(int k=0;k<3;k++)
                    m.set(r.nextInt(),i,j,k);
        for(int i=0;i<5;i++){
            for(int j=0;j<4;j++){
                for(int k=0;k<3;k++)
                    System.out.print(m.get(i,j,k)+" ");     
                System.out.println("");
            }
            System.out.println("\n");
        }
    }
}

class Utils{
    public static int product(int...a){
        int ret=1;
        for (int x:a) ret*=x;
        return ret;
    } 
}

【讨论】:

  • 您好,只是一个更新,我刚刚成功地实现了这个版本,非常感谢您,也感谢本质上具有相同想法的高性能马克。对于任何感兴趣的人来说,这种方法的好处包括只用 1 个 random() 语句而不是 N(维数)在晶格/数组中选择一个随机点。也可以使用 1 个 for 循环而不是 N 个循环来初始化或执行任何批量顺序操作。再次感谢,Hemmer
【解决方案2】:

结帐Java Collections。它包含一个名为 ArrayList 的类,该类会根据需要增长。

一维

List&lt;Boolean&gt; a = new ArrayList&lt;Boolean&gt;();

二维

List&lt;List&lt;Boolean&gt;&gt; b = new List&lt;List&lt;Boolean&gt;&gt;();

三维

List&lt;List&lt;List&lt;Boolean&gt;&gt;&gt; c = new List&lt;List&lt;List&lt;Boolean&gt;&gt;&gt;();

您将以c.get(i).get(j).get(k) 而不是c[i][j][k] 访问该项目,就像在3d 数组中一样。或者更好的是,将它包装在您自己的类中,并在那里使用get() 方法。于是就变成了:

c.get(i, j, k);

编辑

要获得深度为 N 的多维列表,请删除 Boolean 类型指示符并简单地将列表创建为

List level1 = new ArrayList();
List level2 = new ArrayList();
List level3 = new ArrayList();
level1.add(level2);
level2.add(level3);

等等..

【讨论】:

  • 谢谢,这看起来更像是我所追求的那种东西,尽管我仍然不确定它的概括性如何:理想情况下我想要:List..N..> lattice = new List..N..>();其中列表组在运行时定义为 N 深。我怀疑这可能是不可能的......
  • 我认为布尔值列表对于大型集合可能不是理想的性能,您可能希望对整数使用按位算术以节省空间。它需要更多的编码,但性能更好。
  • 你必须放弃类型安全,但它肯定是动态的,请参阅更新的答案
  • 再次感谢,我会试试看。
【解决方案3】:

我将使用术语“排名”来表示数组中的“维度数”。所以向量的秩为 1,矩阵的秩为 2,依此类推。你已经接受了一个答案,你自己承认这不是你想要的。这里有一个替代方案:

回想一下,计算机内存本质上是线性的,编译器在为您提供数组时所做的实际上是将索引表达式转换为线性地址。如果您假设所有数组都在连续的内存中,这是最容易考虑的,但并不总是如此。假设你做了一个声明,如 ARRAY_OF_TYPE[10][10][10],即它有 1000 个元素。然后位置 [3][5][4] 的元素是(我的数组从 1 而非 0 开始索引 - 如果您愿意,可以更改后面的总和)在位置 baseAddress+354*size_of_element_of_TYPE。

我希望你现在知道我要做什么了......

在运行时,您的程序会提示用户输入整数列表。每个整数指定数组维度之一的大小,整数个数指定数组的秩。你的程序做了一些乘法,你分配了一个正确长度的向量。好的,您必须编写索引和取消索引功能,但这些应该相当简单。

等等你有一个数组,它的排名是在运行时建立的。

【讨论】:

  • 射击,你在我还在打字的时候发布了你的答案。 +1。
【解决方案4】:

我在 Google 上快速搜索了“java tensor”,得到了 DJEP,这是否符合您的要求?

【讨论】:

    猜你喜欢
    • 2012-12-27
    • 2016-05-21
    • 1970-01-01
    • 2021-05-19
    • 2014-08-21
    • 1970-01-01
    • 2011-02-06
    • 2010-12-17
    相关资源
    最近更新 更多