Array loops

Dr Andy Evans

[Fullscreen]

Using arrays

  • When we looked at arrays, we saw that you need to assign them a value, like other variables:
    
    array1D[0] = 10.0;
    
    
    And to use them you need to get the data from them, thus:
    
    System.out.println(array1D[0]);
    
    
  • Ok, so having a single name saves us from thinking up new names, but this still seem pretty intensive work if we have to type a line for each array position. What if we have 10000?
  • One key idea will make our lives easier:
    Instead of hardwiring in our position number, why not use the index from a loop to go through all the positions?

Looping through arrays

  • Here's the trick with a simple assignment and request from the array:
    
    int array1D[] = new int[100];
    for (int i = 0; i < array1D.length; i++) {
        array1D[i] = 10;
        System.out.println(array1D[i]);
    }
    
    
  • Note the clever use of array1D.length, which is never reached (and quite right too - remember that numbering of positions starts at zero).

Assignment

  • Obviously we might want more complex assignments, including things like:
    
    array1D[i] = 10 * i;
    array1D[i] = // some code to read data
    
    
  • I cannot express how wonderful this simple slight of hand is. You'll soon take it so for granted that you'll barely notice it, so take some time now to appreciate how clever this really is.

Enlarging arrays

  • Arrays are fixed in size. To enlarge or shrink them, copy them into a larger or smaller array, adding/removing a space where needed.
    
    // using some pre-existing array: arrayA.
    
    int[] arrayB = new int[arrayA.length + 1];
    for (int i = 0; i < arrayA.length; i++) {
        arrayB[i] = arrayA[i];
    }
    arrayA = null; 
    arrayB[arrayB.length - 1] = 10;
    
    
  • Note that we use the same index value to loop through both arrays.
  • Removing a space is more complex. Can you work out how to do it?

Looping

  • But what about multi-dimensional arrays?
  • In geography, where data is often in 2D arrays, this is common. We'd like some way of going to each row and then travelling across it to each space in a row.
  • Well, this is even cleverer. For 2D arrays, we nest two for-loops.
  • Allows us to run across each cell in a series of rows.
  • First, let's look at it without arrays.

Nesting loops

	
for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 3; j++) {
		System.out.println (i + " " + j);
    }
}

Remember, that variables are destroyed as the processing leaves their scope, and re-made if the code runs again.

 

  1. The outer loop starts, then the inner loop starts.
  2. When the inner loop has run once, it returns to the start of the inner loop, not the outer loop.
  3. It keeps doing this until run to completion (j == 3; i still zero).

 

What do you think happens to j then, and where does the code go next?

Nesting loops

	
for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 3; j++) {
		System.out.println (i + " " + j);
    }
}

  1. j is destroyed, and the outer loop increments to i = 1.
  2. The inner loop runs again, j recreated as j = 0.
  3. The inner loop runs to completion.

    Thus, each time the outer loop runs once, the inner loop runs to completion.

  4. This is repeated until the outer loop completes.
  5. The code then moves on.

Nested loops

  • Let's look at i and j:
    i j
    0 0
    0 1
    0 2
    1 0
    1 1
    1 2
  • This is exactly what we need for moving down a row at a time in our array (i) and then running across each row a space at a time (j).

2D arrays

	
int array2D [][] = new int[2][3];

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

		array2D[i][j] = 10;
		System.out.println (array2D[i][j]);

    }
}

Note that i is in scope in the inner block, so we can use array2D[i].length to cope with irregular arrays.

2D issues

  • This is surely one of the neatest algorithms ever!
  • However, it is easy to make mistakes. There are three problems with the below. Can you spot them?
	
int array2D [][] = new int[2][3];

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

		array2D[i][j] = 10;
		System.out.println (array2D[j][i]);

    }
}

The three mistakes are classics that everyone makes, even experienced coders:
	
int array2D [][] = new int[2][3];

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

		array2D[i][j] = 10;
		System.out.println (array2D[j][i]);

    }
}

  1. array2D[j].length : Looping through to the wrong dimension length. This is very common if the lengths are hard-wired in, so avoid that.
	
int array2D [][] = new int[2][3];

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

		array2D[i][j] = 10;
		System.out.println (array2D[j][i]);

    }
}

  1. i++ : Cutting and pasting your outer loop to make your inner loop, and forgetting to change part of the variable use; here, the inner increment should be to j.
	
int array2D [][] = new int[2][3];

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

		array2D[i][j] = 10;
		System.out.println (array2D[j][i]);

    }
}

  1. System.out.println (array2D[j][i]) : Switching the indices the wrong way round. This should be array2D[i][j]. With an non-square array, this will result in trying to read off one side of the array and the program will break. Worse, with a square array, your data will silently be transposed.

 

If you get confused, run through your algorithm by hand on paper, using a 2 by 3 non-square array.

Looping through 2D arrays

  • So, here's our standard code for looping through a raster image or other dataset:
	
for (int i = 0; i < array2D.length; i++) {
    for (int j = 0; j < array2D[i].length; j++) {
		System.out.println(array2D[i][j]);
    }
}

Variations

  • Looping through the same positions in two arrays:
	
for (int i = 0; i < arrayA.length; i++) {
  for (int j = 0; j < arrayA[i].length; j++) {
	  arrayB[i][j] = arrayA[i][j];
  }
}

Variations

  • Looping through two arrays at positions relative to one array (note boundary problem):
	
for (int i = 1; i < arrayA.length - 1; i++) {
    for (int j = 1; j < arrayA[i].length - 1; j++) { 
		arrayB[i][j]= arrayA[i-1][j-1];
    }
}

Boundary problems

Various solutions. Depends on problem context.
Wrap boundaries:
Suitable for modelling abstract landscapes
Only process as many cells as you can:
Suitable for modelling non-abstract landscapes
Only process cells that can have complete processing:
Suitable for image processing

Review

Loops allow us to repeat the same code, with two important results:
  1. we make less mistakes in our code;
  2. we can get arduous jobs, like processing arrays, done easily.