3

Is there a possible way to create an array with a variable number of dimensions?

For example,

int x = 3;
// becomes
int[][][] array = new int[3][3][3];

//and
int y = 4;
//becomes
int[][][][] xray = new int[4][4][4][4];

Part of the reason my examples are so indirect is because I have no idea how one would do something like this.

If I have a variable I would like to create an array with the same number of dimensions as said variable

Mazino
  • 552
  • 6
  • 27
  • can you tell why you want to use that, so we can suggest you another approach ? – Daniel Feb 02 '17 at 02:06
  • see this http://stackoverflow.com/questions/3104504/is-it-possible-to-dynamically-build-a-multi-dimensional-array-in-java – Jonathan Niu Feb 02 '17 at 02:06
  • Can you explain better what do you want to know? The examples are very confusing – nonameable Feb 02 '17 at 02:07
  • @nonameable the examples say that if you want 3 dimensions, it will be 3x3x3 array, 4 dimensions, 4x4x4x4 – Daniel Feb 02 '17 at 02:08
  • @Daniel correct – Mazino Feb 02 '17 at 02:09
  • `I have no idea how one would do something like this` ... you have already successfully created multidimensional arrays. What is the actual question? – Tim Biegeleisen Feb 02 '17 at 02:09
  • if i have a variable i want to create an array with the number of dimensions as the variable – Mazino Feb 02 '17 at 02:09
  • 1
    Can you show us the code which you imagine you would use if you had this ability? You might do better to use one of Java's collection classes. – Tim Biegeleisen Feb 02 '17 at 02:11
  • So you are looking something like Array q = new Array(x) and you have previously set x as the number of dimensions you want? – nonameable Feb 02 '17 at 02:14
  • @nonameable yes, something like that – Mazino Feb 02 '17 at 02:15
  • can you tell us the reason you want this? we certainly can suggest another approach – Daniel Feb 02 '17 at 02:16
  • Im trying to solve 2012 CCC Junior 5 "A Coin Game", and I wanted to store data in the most effective way possible. Heres a link to the question http://wcipeg.com/problem/ccc12j5 – Mazino Feb 02 '17 at 02:18
  • A friend suggested to store states of coin arrangements numerically, so the arrangement of 4 coins would have a 4 digit number, for example, '1233', the magnitude of each digit corresponding to the position of a coin. The one's place digit refers to the position of coin '1', and the thousands the position of coin '4'. He suggested storing these states in a one-dimensional boolean array(for 4 coins, array length of 3333). With this method, there is still wasted data because array index[1999] can never be accessed(there is no 9th position). – Mazino Feb 02 '17 at 02:24
  • This is why I wanted to create a multidimensional array, however there is a variable length of coins, and therefore a variable amount of dimensions in my proposed array – Mazino Feb 02 '17 at 02:25
  • 1
    you can't do this with Java, but that isn't to say its not a thing in other languages; https://en.wikipedia.org/wiki/Variable-length_array – trooper Feb 02 '17 at 03:11

4 Answers4

5

You can't do this directly, but you can simulate it with a 1-dimensional array.

Suppose you have a 2-dimensional array with 3 rows and 4 columns. You could implement this as an array of 12 elements, and write a get routine to get the A[i,j] element like this:

int[] A = new int[12];

int get(int i, int j) {
    return A[4 * i + j];
}

Of course you could write a set method to set an element of the array in the same way.

Moving on to a 3-dimensional array whose dimensions are 3x4x5, you could do something similar:

int[] A = new int[60];

int get(int i, int j, int k) {
    return A[4*5*i + 5*j + k];
}

or a 4-dimensional 3x4x5x6 array:

int[] A = new int[360];

int get(int i, int j, int k, int m) {
    return A[4*5*6*i + 5*6*j + 6*k + m];
}

And so on... you should be able to see the pattern.

Once you've grasped that, it shouldn't be hard to write a class for an array that takes a variable number of dimensions. The get and set methods could take an int... parameter for a variable number of indexes, and the constructor could similarly take an int... to specify the dimensions. The class would have a private 1-dimensional array whose length is the product of all the dimensions. The get and set methods should check each index to make sure it's >= 0 and less than the corresponding dimension, and throw an exception otherwise.

This is how "true" multi-dimensional arrays are implemented under the hood in most languages that support them (Java is not one of those; it only has 1-dimensional arrays whose elements can be references to other 1-dimensional arrays). It's called "row-major order". See https://en.wikipedia.org/wiki/Row-_and_column-major_order for more information (including the generalized formula).

ajb
  • 31,309
  • 3
  • 58
  • 84
1

Short answer you can't. Reason: there is no instance in the world of maths where such a construct could be optimum for anything so the Prophets (K&R and all the good ppl who invent code) left such to the developer who needs it.

But here is my 2 cents: I assume you want to initialize your engine...

engine.init(n);

where n is your dimension. Then be able to put and get things from it.

engine.get(a1,a2,a3,...);
engine.put(val,a1,a2,a3...);

Consider a class like this

public class Engine{
private HashMap<Integer[],Object> storage;
private int dimension=1;
private set<integer[]> keys;
public void init(int n){
dimension=n;
//other initialization task;
}

public Object get(int... a){//use var args
integer[] key=findInkeySet(a);
return storage.get(key);
}

public void put(Object val, int... a){
keys.add(a);
storage.put(a,val);
}
}

ofcause there is need for exception handling and all the other generic coding stuf

Comfort Chauke
  • 126
  • 1
  • 9
0

I try to make this , but return type is Object[] ^^"

public Object[] MakeArray(int s){
  ArrayList l = new ArrayList<>(Collections.nCopies(s, 0));
  for (int i = 1; i < s; i++)
    l = copy(l,s);
  return l.toArray();
}
public ArrayList copy (ArrayList l,int s){
    ArrayList<ArrayList> ret = new ArrayList<>(s);
    for (int i = 0; i < s; i++) 
        ret.add(new ArrayList(l));
    return ret;
}

Arrays.toString(MakeArray(2)) = "[[0, 0], [0, 0]]"
Arrays.toString(MakeArray(3)) = "[[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]"
Deyu瑜
  • 484
  • 4
  • 14
0
public Object createMultidimensionalArray(int dimLength){
    int[] lengths = new int[dimLength];
    for(int i = 0; i < dimLength; i++)
        lengths[i] = dimLength;
    return Array.newInstance(int.class, lengths);
}

Usage example:

int[][][] array3D = (int[][][]) createMultidimensionalArray(3);
System.out.println(Arrays.deepToString(array3D));

Output:

[[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]

Explanation:

The function Array.newInstance(Class<?> componentType, int... dimensions) takes as input the wanted array type and lengths of all dimensions.

dimensions is an array that tells the function what size each dimension should be. To get a 4x4x4x4 array, the following code works:

int[] dimensions = {4, 4, 4, 4};
Object arrObj = Array.newInstance(int.class, dimensions);
int[][][][] arr = (int[][][][]) arrObj;

Array.newInstance(...) returns an Object which can be easily converted to the correct type.

potato
  • 995
  • 11
  • 19