2

i have a 2-dimensional array of ints which i'm looping over. i want to check if an array's element i'm pointing at is within the bounds of that array. say, if i had an array of size 3x2, i would like to be able to do this:

for(int i=some_variable;i<arrayWidth;i++) {
    for (int j=other_variable;j<arrayHeight;j++) {
        if (!array[i][j].ISOUTOFBOUNDS) {
            // do something
        }
    }
}

is there an eloquent way of achieving that or should i just check the indices manually?

ps. i and j can turn out to be negative, too, so i would like to check that as well.

2
  • What's in the array? If int you probably want to use > and < Commented May 28, 2015 at 18:07
  • check if some_variable < arr.length and check if other_variable < arr[i].length also check if they negative Commented May 28, 2015 at 18:16

4 Answers 4

3

You can avoid performing this comparison n² time by pre-computing the valid ranges:

int maxValidI = Math.min(array.length, arrayWidth);
int maxValidJ = Math.min(array[0].length, arrayHeight);
int minValidI = Math.max(0, some_variable);
int minValidJ = Math.max(0, other_variable);

And then iterate i and j from minValidI and minValidJ to maxValidI and maxValidJ.

I hope it will help. Thanks to Andy for notifying me about OP's edit.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 - This is a better approach for rectangular arrays. Even for non-rectangular arrays, you can compute minimum and maximum indices before each inner loop starts. I'm deleting my answer. That said, note that you'll need to compute the minimum indices as well, given the OP's code.
Yeah, actually I was mentioning this aspect in my original answer, but I edited it out because I assumed OP's problem was specific to arrays and not some abstract rectangular bounds :)
Also note that the OP's edit introduced new loop start indices some_variable and other_variable. The iterations might not start from zero.
0

Why not just get the length property of the arrays and use them as you limits in the control structure of if

int arrayWidth = array.length;
for(int i = 0; i < arrayWidth; i++) {
    int arraySize = array[i].length;
    for (int j = 0; j < arraySize; j++) {

    }
}

// or if arrayHeight is from somewhere else

for(int i = 0; i < arrayWidth; i++) {
    int arraySize = array[i].length;
    for (int j = 0; j < arrayHeight; j++) {
        if (arrayHeight <= arraySize) {
            // do something
        }
    }
}

Also note array.length is the size of the array, but does not guarantee the index contains a non null value. I would use ArrayList instead since it contains size() which is the size of the non null values.

https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#size()

https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#asList(T...)

1 Comment

I like @TomG solution better
0

You can't do it in the form you wrote it, but you can do something close:

if (isInBounds(array,i,j)) { ... }

Then you just need to implement isInbounds.

You could make that method completely generic if you wanted to. E.g. the following works for any array or array of arrays or ..., even nonuniform ones (e.g. an array of different sized arrays). Only catch is it won't work on arrays of primitive types cuz of the cast to Object[]. Probably need more reflection stuff to handle that.

public static boolean isInBounds(Object arrayObj, int...indexes) {
  for (int i = 0; i < indexes.length; i++) {
    if (arrayObj == null || !arrayObj.getClass().isArray()) {
      return false; // we had too many indexes... ended up indexing a leaf element
    }
    Object[] array = (Object[]) arrayObj;
    if (indexes[i] < 0 || indexes[i] >= array.length) {
      return false;
    }
    arrayObj = array[indexes[i]];
  }
  return true;
}

Comments

0

i figured out a different way to do this.

for(int i=some_variable;i<arrayWidth;i++) {
    for (int j=other_variable;j<arrayHeight;j++) {
        try {
            int tmp=array[i][j];
            // do something
        } catch (ArrayIndexOutOfBoundsException e) {
            continue;
        }
    }
}

what do you think of this approach? it saves us from having to pre-compute the ranges and makes the code shorter and easier.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.