简体   繁体   中英

Move null elements of each row in a 2D array to the end of that row

Let's say I have a 2d array which looks like this:

[[O, X, null, O, O, null, null], [null, null, O, null, null, O, O]]

And I want it to look like this:

[[O, X, O, O, null, null, null], [O, O, O, null, null, null, null]]

I tried this, but it's not working:

String[][] a = new String[row][col];
String[][] b = new String[row][col];

for (int i = 0; i < a.length; i++) {
    for (int j = 0; j < a.length; j++) {
        if (a[i][j] != null) {
            a[i][j] = b[i][j];
        } else {
            b[i][j] = a[i][j + 1];
        }
    }
}

The first thing that stands out to me is you never check the length of the inner array. Given the example, it will only ever check the first 2 elements.

// Before
for (int j = 0; j < status.length; j++)

// Solution
for (int j = 0; j < status[i].length; j++)

As for the specific problem, you could do it by keeping track of the index of the first null and moving any elements you encounter to it.

int lastEmpty = 0;

for (int j = 0; j < status[i].length; j++) {
    // Move to the best compressed position
    if (status[i][j] != null && status[i][lastEmpty] == null) {
        status[i][lastEmpty] = status[i][j];
        status[i][j] = null;
    }

    // Shift to always be the first null
    if (status[i][lastEmpty] != null) {
        lastEmpty++;
    }
}

Some points to fix the problem

  • You need to use a[i].length for inner loop
  • a[i][j] = b[i][j]; here you need to assign a value in b
  • You need to use a counter index for b 2D array's every row and whenever found not-null increment this after storing and remaining index are by defult null.
for (int i = 0; i < a.length; i++) {
  int indNew = 0; // Index for every row
  for (int j = 0; j < a[i].length; j++) {
    if (a[i][j] != null) {
      b[i][indNew] = a[i][j]; // store not null value
      indNew++;  // increase after storing
    }
  }
}

You can iterate over this array and for each row filter out the null elements and collect the remaining ones toArray of the same length where the nulls go last:

String[][] arr1 = {
        {"O", "X", null, "O", "O", null, null},
        {null, null, "O", null, null, "O", "O"}};

String[][] arr2 = Arrays.stream(arr1)
        .map(row -> Arrays.stream(row)
                // filter out null elements
                .filter(Objects::nonNull)
                // new array of the same length, nulls last
                .toArray(q -> new String[row.length]))
        .toArray(String[][]::new);
// output
Arrays.stream(arr2).map(Arrays::toString).forEach(System.out::println);
[O, X, O, O, null, null, null]
[O, O, O, null, null, null, null]

See also: Remove null from old 2d array and put the not null elements in a new 2d array

You do not need to create new 2D array to store its updated version, null values can be simply moved to the end of each row and then use Arrays.fill to set null starting from the calculated index.

update: the method can be generic

public static <T> void moveNulls(T[][] status) {
    for (T[] row : status) {
        if (null == row) {
            continue;
        }
        int id = 0;
        for (int i = 0; i < row.length; i++) {
            if (row[i] != null) {
                row[id++] = row[i];
            }
        }
        Arrays.fill(row, id, row.length, null);
    }
}

Test

String[][] status = {
        {"aaa", null, "bbb", null, null, "ccc"},
        {null, "bbb", null, null, "ccc", "ddd", null, "eee"},
        {null, null, "fff", null, "ccc", "ddd", null, "ggg", null},
};

moveNulls(status);
for (String[] row : status) {
    System.out.println(Arrays.toString(row));
}

Output

[aaa, bbb, ccc, null, null, null]
[bbb, ccc, ddd, eee, null, null, null, null]
[fff, ccc, ddd, ggg, null, null, null, null, null]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM