3ck
3ck

Reputation: 539

Remove null elements from String array where "All elements are null"

I am tasked with fixing a problem where this code returns string values but because the iterations add null elements it needs to trim or remove those. During debug the value of the array contains mostly "All elements are null", but other solutions like data.removeAll(Collections.singleton(null)); do not work because it is the elements that are null and it still returns as the original size. Is there a way to remove these elements after the iterations of the initial loop or should this be done inside the loop where data is assigned the "value"?

Code:

    private String[][] getStringsFromSpreadSheet(Sheet ws) {
    int rowNum = ws.getLastRowNum() + 1;
    int colNum = ws.getRow(0).getLastCellNum();
    String[][] data = new String[(rowNum - 1)][colNum];

    int k = 0;
    for (int i = 1; i < rowNum; i++) {
        ws.getRow(i);
        if (ws.getRow(i) != null) {
            for (int j = 0; j < colNum; j++) {
                if (ws.getRow(i).getCell(j) != null) {
                    String value = ws.getRow(i).getCell(j).toString();
                    if (!value.toString().isEmpty()) {
                        data[k][j] = value;
                    }
                }
            }
        }
        k++;
    }
    return data;
}

Upvotes: 2

Views: 2025

Answers (3)

azurefrog
azurefrog

Reputation: 10955

You can easily trim out null values from a List, but you've been trying to convert your array to a List incorrectly.

Since you've got a two-dimensional array, you need to create a nested list (List<List<String>>) to store the data.

For instance, let's start with a mostly empty String[][]:

    String[][] data = new String[3][3];
    data[0][0] = "foo";
    data[1][1] = "bar";

    //data is a 3x3 array
    for (int i=0; i<data.length; i++) {
        System.out.println(Arrays.toString(data[i]));
    }
    //[foo, null, null]
    //[null, bar, null]
    //[null, null, null]

We can take each sub-array, convert it to a list, trim it, and then add the non-empty lists to an enclosing list, like so:

    List<List<String>> dataList = new ArrayList<>();
    for (int i=0; i<data.length; i++) {
        List<String> temp = new ArrayList<>();
        Collections.addAll(temp, data[i]);
        temp.removeAll(Collections.singleton(null));
        if (!temp.isEmpty()) {
            dataList.add(temp);
        }
    }

We can then convert the list back to a String[][], which will be "trimmed" of null data, like so:

    String[][] newData = new String[dataList.size()][];
    for (int i=0; i<dataList.size(); i++) {
        List<String> subList = dataList.get(i);
        newData[i] = subList.toArray(new String[subList.size()]);
    }

    //newData is a 2x1 array
    for (int i=0; i<newData.length; i++) {
        System.out.println(Arrays.toString(newData[i]));
    }
    //[foo]
    //[bar]

Upvotes: 1

gonzo
gonzo

Reputation: 2121

Based on your comments it seems that you have to return a String[][] for getStringsFromSpreadSheet. Is this correct? If so there is not a nice way to keep track of how many cells are null/not null. 2D arrays have to be rectangular. So if one of your rows has 3 columns populated and one row only has 1 column populated, the array has to be at least 3 columns wide. I have tried to represent this visually below.

Row | Column 1  | Column 2  | Column 3  |
 1  | something | something | something |
 2  | something |    null   |    null   |

So for the above data you have to declare a 2D array at least 2x3 to fit all of your data. No matter what, if one of your rows does not populate all 3 columns, you will always have a null cell for that row. Array.length will always return the size of the array, never the count of how many are null/not null.

Your options are limited if you can only return a String[][]. If you are able to return something else, we can work through some options.

Upvotes: 0

StackFlowed
StackFlowed

Reputation: 6816

All you need to do is set it to blank string. check the else clause.

private String[][] getStringsFromSpreadSheet(Sheet ws) {
int rowNum = ws.getLastRowNum() + 1;
int colNum = ws.getRow(0).getLastCellNum();
String[][] data = new String[(rowNum - 1)][colNum];

int k = 0;
for (int i = 1; i < rowNum; i++) {
    ws.getRow(i);
    if (ws.getRow(i) != null) {
        for (int j = 0; j < colNum; j++) {
            if (ws.getRow(i).getCell(j) != null) {
                String value = ws.getRow(i).getCell(j).toString();
                if (!value.toString().isEmpty()) {
                    data[k][j] = value;
                }
            } else {
                data[k][j] = "";
            }
        }
    }
    k++;
}
return data;

Now the data would not have any null values but it may have blank / empty strings.

Upvotes: 0

Related Questions