Search code examples
javastringmultidimensional-arraynullragged

Removing a String from a ragged 2D String array and shortening the array in the process


My professor gave out a review question for our midterm this week that I'm confused on:

Write a method that is given a two-dimensional (ragged) array of String objects and returns a two-dimensional (ragged) array of String objects where all the null entries have been removed. For example, if the original array has the data (NULL represents a null reference):

{"John", null, "Mary", "George", null},{null, "Pete", "Rick"},{null, null, null}};

the result generated by your method will be a two-dimensional array with three rows.

{"John", "Mary", "George"},{"Pete", "Rick"},{}}; // last row will be empty

The code I have is:

public static String[][] removeNull2D(String[][] ragged) {
    int counter = 0;
    int nullCounter = 0;
    String[][] array; // isn't initialized

    // doesn't work I tested in debugger, need a way to shorten each row by the amount of null values it has
    for (int i = 0; i < ragged.length; i++) {
        for (int j = 0; j < ragged[i].length; j++) {
            if (ragged[i][j] == null) {
                nullCounter++;
                for (j = 0; j < ragged[i].length; j++) {
                    array = new String[ragged.length][ragged[i].length - nullCounter];
                }
            }
        }
    }
    // based off 1D array approach
    for (int i = 0; i < ragged.length; i++) {
        for (int j = 0; j < ragged[i].length; j++) {        
            if (ragged[i][j] != null) {
                array[i][counter++] = ragged[i][j];
            }
        }
    }
    return ragged;
}

I understand I need to count the amount of null values in each row and subtract that from the total length of each row for the String array "array" (bad name I know). I thought maybe if I made a method for a 1D array, it would help me understand the logic a little better:

public static String[] removeNull1D(String[] a) {
    String[] array = new String[a.length - 1];
    int counter = 0;

    for (int i = 0; i < a.length; i++) {
        if (a[i] != null) {
            array[counter++] = a[i];
        }
    }
    a = array;
    return array;
}

Still confused how the logic applies to the 2D ragged array method, any clarification would be appreciated! Also, I don't believe I can import anything (are not supposed to at least), and once again this is just a review question, so I'm not stressing about getting an answer, just trying to understand the logic behind it.


Solution

  • You could try it like this:

    public static void main(String[] args) {
        String[][] ragged = { { "John", null, "Mary", "George", null }, { null, "Pete", "Rick" }, { null, null, null } };
    
        String[][] cleaned = new String[ragged.length][];
        for (int i = 0; i < ragged.length; i++) {
            cleaned[i] = clean(ragged[i]); // Apply clean method to each sub array.
        }
    
        System.out.println(Arrays.deepToString(cleaned));
    }
    
    private static String[] clean(String[] dirty) {
        int nonNullCount = 0;
        for (String string : dirty) {
            if (string != null) {
                nonNullCount++; // Count non-null Strings.
            }
        }
        String[] clean = new String[nonNullCount]; // Create array for non-null Strings.
        int cleanIndex = 0;
        for (String string : dirty) {
            if (string != null) {
                clean[cleanIndex] = string; // Insert only non-null String at index.
                cleanIndex++; // Only then update index.
            }
        }
        return clean;
    }
    

    Seems a little bit inelegant to me, but at the moment I can't think of a way to prevent the double loop in clean(String[] dirty)

    Nevertheless, it outputs [[John, Mary, George], [Pete, Rick], []] as desired.

    Edit: Updated some commentary.