Reputation: 1
I want to sort a 2D array in ascending order using Arrays.sort()
.
For example, I have this array:
[3,8,5]
[1,6,7]
[2,4,9]
After sorting, the output should be:
[1,2,3]
[4,5,6]
[7,8,9]
Wrote code like this, but it sorts by rows:
package domain;
import java.util.Arrays;
public class Exercise {
private int[][] matrix = {
{34, 2, 15, 12, 56},
{3, 67, 6, 21, 9},
{22, 5, 18, 65, 10},
{52, 36, 112, 90, 0},
{19, 48, 73, 16, 88}};
// Method that displays the array
public void DisplayArray() {
for (int[] row : matrix) {
System.out.println(Arrays.toString(row));
}
}
public void Sorting() {
for (int[] row : matrix) {
Arrays.sort(row);
}
}
}
Upvotes: 0
Views: 510
Reputation:
You can first flatten this 2d array to a one dimension, then sort a flat array with Arrays.sort
method, and then assemble back a 2d array of the same dimensions with elements from the sorted flat array:
// original array
int[][] arr = {
{3, 8, 5},
{1, 6, 7},
{2, 4, 9}};
// flatten a 2d array
int[] flatArr = Arrays.stream(arr).flatMapToInt(Arrays::stream).toArray();
// sorting
Arrays.sort(flatArr);
// reassemble a 2d array of the same dimensions from a flat array
AtomicInteger flatIndex = new AtomicInteger(0);
// iterate over the rows and their elements of
// the original array and sequentially fill the
// new array with elements from the flat array
int[][] sorted = Arrays.stream(arr)
.map(row -> Arrays.stream(row)
.map(j -> flatArr[flatIndex.getAndAdd(1)])
.toArray())
.toArray(int[][]::new);
// output
Arrays.stream(sorted).map(Arrays::toString).forEach(System.out::println);
//[1,2,3]
//[4,5,6]
//[7,8,9]
See also:
• How do you rotate an array 90 degrees without using a storage array?
• Filling a jagged 2d array first by columns
Upvotes: 0
Reputation: 19545
Using streams, it is possible to convert the 2D array into a stream of integers and then recollect it to 2D array:
public static int[][] sort2D(int[][] arr) {
int rows = arr.length;
int cols = arr[0].length;
int[] row = {0};
return Arrays.stream(arr)
.flatMapToInt(Arrays::stream)
.sorted()
.boxed()
.collect(Collectors.groupingBy(x -> row[0]++ / cols))
.values()
.stream()
.map(r -> r.stream().mapToInt(Integer::intValue).toArray())
.toArray(int[][]::new);
}
Test
int[][] arr = {
{9, 7, 5, 4},
{3, 12, 11, 8},
{6, 1, 2, 10}
};
int[][] sorted = sort2D(arr);
Arrays.stream(sorted)
.map(Arrays::toString)
.forEach(System.out::println);
Output
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
Update
A simpler solution is possible using method Stream::collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
:
public static int[][] sort2D(int[][] arr) {
int rows = arr.length;
int cols = arr[0].length;
AtomicInteger ix = new AtomicInteger(0); // int[] ix = {0}; can be used too
return Arrays
.stream(arr)
.flatMapToInt(Arrays::stream)
.sorted()
.collect(
() -> new int[rows][cols], // supplier creating the result array
(a, x) -> a[ix.get() / cols][ix.getAndIncrement() % cols] = x, // populate with sorted data
(arr1, arr2) -> {} // nothing to combine
);
}
Upvotes: 1
Reputation: 103
You can try this. got my reference here java Arrays.sort 2d array
Arrays.sort(matrix, (a, b) -> a[0] - b[0]);
Upvotes: 0
Reputation: 5294
The problem can be broken down into three parts.
n
in a single vectorn
With your example input
int[][] arr = { {3,8,5},{1,6,7},{2,4,9} };
and method:
int[][] sorted(int[][] in) {
int[] all = new int[in.length * in.length]; // assumption: square matrix
int i = 0;
for (int[] row : in) {
for (int el : row) {
all[i] = el;
i++;
}
}
Arrays.sort(all); // sort all elements in single vector
// put sorted elements in your "output" array
int[][] out = new int[in.length][in.length];
int row = 0;
int col = 0;
for (int el : all) {
// note col,row and not row,col!
out[col][row] = el;
row++;
if (row == in.length) {
row = 0;
col++;
}
}
return out;
}
You have
int[][] sorted = sorted(arr);
Upvotes: 0