Reputation: 1261
I'm trying to create a method that will sum up the potential items and return that sum from an array. Here are some sample inputs that would be expected:
arraySum(new int[10]); // 10
arraySum(new int[2][5]); // 10
arraySum(new int[5][5][5]); // 125
The problem is I can never actually know how many dimensions I am working with. So far, I've found that calling String.valueOf(array)
on an array returns a string which contains [
characters for however many dimensions exist in the array:
String.valueOf(new int[10]); // [I@hash_code
String.valueOf(new int[5][2]); // [[I@hash_code
String.valueOf(new int[5][5][5]); // [[[I@hash_code
I can use this to find out the exact amount of dimensions that exist for that array by doing String.valueOf(array).split("\\[").length - 1
. I'm not sure what I can do from this point however.
public int arraySum(final Object array) {
checkArgument(array.getClass().isArray()); // from com.google.common.base.Preconditions
final int dimensions = String.valueOf(array).split("\\[").length - 1;
int sum = 0;
// somehow loop n-times over here to count up
return sum;
}
Normally when iterating on multi-dimensional arrays, you would have multiple loops inside of one another, but in my case, I would need n-loops, which I obviously can't hardcode. What can I do?
Upvotes: 0
Views: 83
Reputation: 1261
My solution was to use a for loop to iterate on the dimensions and perform multiplication of the lengths:
public int arraySum(Object array) {
int count = 1; // necessary to prevent initial 0 multiplication
int dim = ...; // the dimensions of the array
for (int i = 0; i < dim; ++i) {
int len = Array.getLength(array);
count *= len;
if (len == 0) {
break; // a length of 0 at any point means no potential items
}
array = Array.get(array, 0); // never fails, since len must be greater than 1 by this point
}
}
This gives me the potential length, or otherwise the capacity of the array to hold a specific type.
arraySum(new int[10]); // 1 array with 10 ints, capacity 10 * 1 == 10
arraySum(new float[10][2]); // 2 arrays with 10 floats, capacity of 2 * 10 == 20
arraySum(new CustomType[5][5]); // 5 arrays with 5 custom types, capacity 5 * 5 == 25
Upvotes: 0
Reputation: 2492
Do it this way:
public static int arraySum(final Object[] array) {
if(array.length == 0) return 0;
return array.length * ((array[0] instanceof Object[]) ? arraySum((Object[]) array[0]) : 1);
}
You can also overload this method for primitives arrays. Here is how I would do it with minimal code duplication:
private static int doArraySum(Object array) {
if(array == null || !array.getClass().isArray()) return 1;
int length = Array.getLength(array);
if(length == 0) return 0;
return length * doArraySum(Array.get(array, 0));
}
public static int arraySum(Object[] array) {
return doArraySum(array);
}
public static int arraySum(int[] array) {
return doArraySum(array);
}
// other primitives
If the length of the sub-arrays may not be equal, you should use addition instead of multiplication:
private static int doArraySum(Object array) {
if (array == null || !array.getClass().isArray()) return 1;
return IntStream
.range(0, Array.getLength(array))
.map(i -> doArraySum(Array.get(array, i)))
.sum();
}
Example:
int[][] array = new int[2][];
array[0] = new int[2];
array[1] = new int[3];
arraySum(array); // 5
Upvotes: 1