Skip to content
Advertisement

Sort 2D array by average value of each line

I have complex task to differently sort two dimensional array manually. So far I get done those tasks:

  1. User needs to input row size from 10 – 20,

  2. Generate 2D array where row size is user input and column size is randomly generated from 10-50,

  3. Each array is filled with randomly generated numbers from 100 – 999,

  4. Output each array row by its descending value,

  5. Output average value of each array line,

  6. Output on screen array with biggest average value,

  7. So far I can’t solve task Nr. 7. Output sorted two dimensional array by each lines average value. Tried to implement new arrayAverage in loop to sort lines it didn’t work. Array just need to be sorted without creating new array.

import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;

public class SortArray2D {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Sorting two dimensional arrays!!!");
        System.out.print("Enter arrays 1st dimension size 10 - 20: ");
        int array1stDsize = sc.nextInt();
        int array2ndDsize = new Random().nextInt(40) + 10;
        System.out.println();
        sc.close();

        if (array1stDsize > 20 || array1stDsize < 10) {
            System.out.println("The number you entered is too big or too small!!!");
        } else {
            //initializing array 
            int[][] array = new int[array1stDsize][array2ndDsize];
            for (int i = 0; i < array.length; i = i + 1) {
                for (int j = 0; j < array[i].length; j = j + 1) {
                    int input = new Random().nextInt(900) + 100;
                    array[i][j] = input;
                }
            }
            System.out.println("Array element output: ");
            arrayOutput(array);
            // array element sorting from biggest to smallest 
            for (int k = 0; k < array.length; k++) {
                for (int i = 1; i < array[k].length; i++) {
                    for (int j = i; j > 0; j--) {
                        if (array[k][j] > array[k][j - 1]) {
                            int element = array[k][j];
                            array[k][j] = array[k][j - 1];
                            array[k][j - 1] = element;
                        }
                    }
                }
            }
            System.out.println();
            System.out.println("Descending Array element output: ");
            arrayOutput(array);

            System.out.println();
            System.out.println("Average value output by array: ");
            float[] arrayAverage = new float[array1stDsize];
            float average = 0;
            for (int i = 0; i < array.length; i = i + 1) {
                for (int j = 0; j < array[i].length; j = j + 1) {
                    average = average + array[i][j];
                }
                average = (float) (Math.round((average / array[i].length) * 100.0) / 100.0);
                System.out.println(i + ". array average value: " + average);
                arrayAverage[i] = average;
            }

            System.out.println();
            System.out.println("New array from average values: ");
            System.out.println(Arrays.toString(arrayAverage));

            System.out.println();
            System.out.println("Most valuest array is: ");
            double max = 100;
            int row = 0;
            for (int i = 0; i < arrayAverage.length; i++) {

                if (max < arrayAverage[i]) {
                    max = arrayAverage[i];
                    row = i;
                }
            }
            System.out.print("Its founded " + row + ". row and it's value is: ");
            for (int j = 0; j < array[row].length; j = j + 1) {
                System.out.print(" " + array[row][j]);
            }

            System.out.println();
            System.out.println();

            //2D array sorting by average values
        }
    }

    public static int[][] arrayOutput(int[][] array) {
        for (int i = 0; i < array.length; i = i + 1) {
            for (int j = 0; j < array[i].length; j = j + 1) {
                if (j == 0) {
                    System.out.print("{ " + array[i][j]);
                } else {

                    System.out.print(", " + array[i][j]);
                }
            }
            System.out.print(" }");
            System.out.println();

        }
        return array;
    }
}

Advertisement

Answer

The part of your code that calculates the average:

    float[] arrayAverage = new float[array1stDsize];
    float average = 0;
    for (int i = 0; i < array.length; i = i + 1) {
        for (int j = 0; j < array[i].length; j = j + 1) {
            average = average + array[i][j];
        }
        average = (float) (Math.round((average / array[i].length) * 100.0) / 100.0);
        System.out.println(i + ". array average value: " + average);
        arrayAverage[i] = average;
    }

is slightly wrong, you need to set the average variable to zero before calculating the average of the next rows:

  ...
  arrayAverage[i] = average;
  average = 0;

With the Java Streams one can get the matrix sorted by average of rows pretty elegantly, namely:

Arrays.sort(array, comparingDouble(row -> IntStream.of(row)
                                                   .average()
                                                   .getAsDouble()));

To sort the array one uses the method Arrays.sort, and then for each row one gets its average as a double value IntStream.of(row).average().getAsDouble(), and used as the sorting parameter comparingDouble(....).

A running example:

import java.util.Arrays;
import java.util.Comparator;
import java.util.stream.IntStream;
import static java.util.Comparator.comparingDouble;

public class Test {
    public static void main(String[] args) {
        int array[][] = {{10, 20, 30},{40, 50, 60}, {1,2,3} };
        Arrays.sort(array, comparingDouble(row -> IntStream.of(row).average().getAsDouble()));
        Arrays.stream(array).map(Arrays::toString).forEach(System.out::println);
    }
}

The output:

[1, 2, 3]
[10, 20, 30]
[40, 50, 60]

For the reverse order use instead:

Arrays.sort(array, comparing(row -> IntStream.of(row).average().getAsDouble(), reverseOrder()));

The output:

[40, 50, 60]
[10, 20, 30]
[1, 2, 3]

EDIT: WITH NO STREAMS

Without using streams what you can do is the following:

1 – Get the array with the averages of the matrix rows:

float[] arrayAverage = average(matrix);

You already know how to calculate the average, therefore you just need to extract a method out of the code that you have created, namely:

private static float[]average(int[][] array) {
    float[] arrayAverage = new float[array.length];
    float sum = 0;
    for (int i = 0; i < array.length; i++) {
        for (int j = 0; j < array[i].length; j++) {
            sum += array[i][j];
        }
        arrayAverage[i] = (float) (Math.round((sum / array[i].length) * 100.0) / 100.0);
        sum = 0;
    }
    return arrayAverage;
}

2 – Create an array that will represent the rows and initialized as the following:

int [] row_position = new int [arrayAverage.length];
for(int i = 0; i < row_position.length; i++)
    row_position[i] = i;

3 – Sort the arrayAverage using the easiest sort, the bubble sort. While sorting that array update accordingly the positions stored on the row_position:

for(int i=0; i < arrayAverage.length; i++){
    for(int j=1; j < (arrayAverage.length-i); j++){
        if(arrayAverage[j-1] > arrayAverage[j]){
            float temp = arrayAverage[j-1];
            arrayAverage[j-1] = arrayAverage[j];
            arrayAverage[j] = temp;
            int temp_pos = row_position[j-1];
            row_position[j-1] = row_position[j];
            row_position[j] = temp_pos;
        }
    }
}

4 – Now that you have the row_positions array that tells you how the sorted rows should be rearranged, you just need to swap the rows accordingly:

    int[][] tmp_matrix = new int [matrix.lenght][];
    for (int i = 0; i < tmp_matrix.length; i++) {
        tmp_matrix[i] = matrix[row_position[i]];
    }
    matrix = new_matrix;

Bear in mind, however, that for simplicity-sake I have assumed a quadratic matrix of NxN, and the above solution can be improved performance-wise.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement