Insert column in desired location of 2D array - java

I'm looking to choose a column of my array, lets say column 2. I want this column to be inserted at a specific location in the 2D array, lets say column 4.
For example:
1 3 5 5 2
2 4 6 2 1
3 6 9 1 1
The desired output would be:
1 5 5 3 2
2 6 2 4 1
3 9 1 6 1
I know I could loop the following code until I 1 by 1 swap every column until the column is in the desired location.
for (int[] array1 : array) {
int temp = array1[col1];
array1[col1] = array1[col1];
array1[col2] = temp;
}
However, if I'm using large matrices such as 30 columns wide, this would be incredibly inefficient. Is there a way to insert the column anywhere in the 2D array without iterating through each swap until it is in the right spot?

Possibly, a performance may be improved by using parallel processing with streams.
IntStream of row indexes should be used to handle each row separately.
// basic shift method
// from, to - indexes starting from 1
public static void shiftArray(int[] arr, int from, int to) {
int tmp = arr[from - 1];
for (int i = from; i < to; i++) {
arr[i - 1] = arr[i];
}
arr[to - 1] = tmp;
}
public static void main(String[] args) {
int[][] arr2d = {
{1, 3, 5, 5, 2},
{2, 4, 6, 2, 1},
{3, 6, 9, 1, 1}
};
int fromColumn = 2;
int toColumn = 4;
IntStream.range(0, arr2d.length)
.parallel()
.forEach(i -> shiftArray(arr2d[i], fromColumn, toColumn)); // shift each row in parallel
// print the 2D array after shift
Arrays.stream(arr2d)
.map(Arrays::toString)
.forEach(System.out::println);
}
Output:
[1, 5, 5, 3, 2]
[2, 6, 2, 4, 1]
[3, 9, 1, 6, 1]

Try this.
public static void moveColumn(int[][] matrix, int from, int to) {
--from; --to; // If column number begins with zero, remove this line.
int srcPos = from < to ? from + 1 : to;
int destPos = from < to ? from : to + 1;
int length = Math.abs(from - to);
for (int[] array : matrix) {
int temp = array[from];
System.arraycopy(array, srcPos, array, destPos, length);
array[to] = temp;
}
}
and
int[][] matrix = {
{1, 3, 5, 5, 2},
{2, 4, 6, 2, 1},
{3, 6, 9, 1, 1}
};
moveColumn(matrix, 2, 4);
for (int[] row : matrix)
System.out.println(Arrays.toString(row));
output
[1, 5, 5, 3, 2]
[2, 6, 2, 4, 1]
[3, 9, 1, 6, 1]

Related

how to sort two dimensional array by one column in Java

So what I want is this
int[][] arr=new int[2][8];
input:
1 1 3 1 5 3 7 1
5 2 4 8 3 7 5 2
output:
1 1 5 3 1 7 3 1
2 2 3 4 5 5 7 8
you can see that it is sorted by the second row in ascending order and the first row just follows,
how can I do this? help, please.
I tried doing below
Arrays.sort(arr[1]);
but I don't think it is working. It does sort the second row in ascending order but the first row is not matching the initial pair with the second row
Try this.
public static void main(String[] args) {
int[][] array = {
{1, 1, 3, 1, 5, 3, 7, 1},
{5, 2, 4, 8, 3, 7, 5, 2}
};
List<int[]> list = new AbstractList<int[]>() {
#Override
public int[] get(int index) {
return new int[] {array[1][index], array[0][index]};
}
#Override
public int[] set(int index, int[] value) {
int[] old = get(index);
array[1][index] = value[0];
array[0][index] = value[1];
return old;
}
#Override
public int size() {
return array[0].length;
}
};
Collections.sort(list, Arrays::compare);
for (int[] row : array)
System.out.println(Arrays.toString(row));
}
output:
[1, 1, 5, 3, 1, 7, 3, 1]
[2, 2, 3, 4, 5, 5, 7, 8]
Or
public static void main(String[] args) {
int[][] array = {
{1, 1, 3, 1, 5, 3, 7, 1},
{5, 2, 4, 8, 3, 7, 5, 2}
};
int[] sortedIndexes = IntStream.range(0, array[0].length)
.boxed()
.sorted(Comparator.comparing((Integer i) -> array[1][i])
.thenComparing(i -> array[0][i]))
.mapToInt(Integer::intValue)
.toArray();
int[][] output = IntStream.range(0, array.length)
.mapToObj(r -> IntStream.range(0, array[r].length)
.map(i -> array[r][sortedIndexes[i]])
.toArray())
.toArray(int[][]::new);
for (int[] r : output)
System.out.println(Arrays.toString(r));
}
It may be implemented using helper method(s) to transpose the input array, then transposed array may be sorted by column, and transposed again to restore the original rows/cols:
// create new array to store transposed
public static int[][] transpose(int[][] src) {
return transpose(src, new int[src[0].length][src.length]);
}
// use existing array to store the transposed
public static int[][] transpose(int[][] src, int[][] dst) {
for (int i = 0, n = src.length; i < n; i++) {
for (int j = 0, m = src[i].length; j < m; j++) {
dst[j][i] = src[i][j];
}
}
return dst;
}
Method sortByColumn (reusing the input array):
public static void sortByColumn(int[][] arr, Comparator<int[]> comparator) {
int[][] toSort = transpose(arr);
Arrays.sort(toSort, comparator);
transpose(toSort, arr);
}
Test:
int[][] arr = {
{7, 1, 3, 1, 5, 3, 1, 4, 4},
{5, 2, 4, 8, 3, 7, 5, 2, 5}
};
sortByColumn(arr, Comparator.comparingInt(col -> col[1]));
for (int[] row : arr) {
System.out.println(Arrays.toString(row));
}
Output:
in the first row values appear in the insertion order after sorting by the second element in each column.
[1, 4, 5, 3, 7, 1, 4, 3, 1]
[2, 2, 3, 4, 5, 5, 5, 7, 8]
Square arrays (width == height) may be transposed more efficiently without creating additional array:
public static int[][] transposeSquare(int[][] arr) {
for (int i = 0, n = arr.length; i < n; i++) {
// select the elements only above the main diagonal
for (int j = i + 1, m = arr[i].length; j < m; j++) {
int tmp = arr[i][j];
arr[i][j] = arr[j][i];
arr[j][i] = tmp;
}
}
return arr;
}

Index of center of mxn matrix. if center does not exist, return the index of the square closest to the center with the highest integer

Trying to write a method which returns the center of the MxN matrix and if the center does not exist the method should return the index of the square closest to the center with the highest integer value
Eg 1. -
[[5, 7, 8, 6, 3],
[0, 0, 7, 0, 4],
[4, 6, 3, 4, 9],
[3, 1, 0, 5, 8]]
return [1,2] (Center does not exist so closest to the center is [[0,
7, 0],[6, 3, 4]] and 7 is the max value)
Eg 2. -
[[5, 7, 8, 6],
[0, 0, 7, 0],
[4, 6, 3, 4],
[3, 1, 0, 5]]
return [1,2] (Center does not exist so closest to center is [[0,7],[6,3]] and 7 is the max value)
Eg 3. -
[[5, 7, 8],
[0, 0, 7],
[4, 6, 3]]
return [1,1] (Center exists)
private static int[] centerCoordinates(int[][] matrix) {
int row = matrix.length;
int col = matrix[0].length;
if (row % 2 != 0 && col % 2 != 0 && row == col)
return new int[]{row / 2, col / 2};
if (row % 2 == 0 && col % 2 == 0 && row == col) {
//calculate the max of internal square Eg 2.
return new int[]{x, y};
}
//where row!=col
}
I'm assuming you made a mistake in example 1, you gave the right answer, but I think the cells considered should only be [[7],[3]] and not 3 columns wide.
Basically if the dimension is even check length/2-1 and length/2.
If the dimension is odd check only length/2.
Loop through and take max.
private static int[] centerCoordinates(int[][] matrix) {
int row = matrix.length;
int col = matrix[0].length;
int[] ans = new int[]{row/2-(1-(row%2)), col/2-(1-(col%2))};
int best = Integer.MIN_VALUE;
for(int i=row/2-(1-(row%2));i<row/2+1;i++){
for(int j=col/2-(1-(col%2));j<col/2+1;j++){
if(matrix[i][j]>best){
best = matrix[i][j];
ans = new int[]{i,j};
}
}
}
return ans;
}
For this case the center point exists only for those matrices where m == n and both are odd numbers. If this condition is not met, then take central region (m, n):
even - from x / 2 to length - x / 2
odd - from x / 2 - 1 to length - x / 2 + 1
public static void main(String[] args) {
int[][] m1 = {
{5, 7, 8, 6, 3},
{0, 0, 7, 0, 4},
{4, 6, 3, 4, 9},
{3, 1, 0, 5, 8}};
int[][] m2 = {
{5, 7, 8, 6},
{0, 0, 7, 0},
{4, 6, 3, 4},
{3, 1, 0, 5}};
int[][] m3 = {
{5, 7, 8},
{0, 0, 7},
{4, 6, 3}};
int[][] cr1 = centralRegion(m1);
int[][] cr2 = centralRegion(m2);
int[][] cr3 = centralRegion(m3);
Arrays.stream(cr1).map(Arrays::toString).forEach(System.out::println);
// [0, 7, 0]
// [6, 3, 4]
System.out.println(maxValue(cr1)); // 7
Arrays.stream(cr2).map(Arrays::toString).forEach(System.out::println);
// [0, 7]
// [6, 3]
System.out.println(maxValue(cr1)); // 7
Arrays.stream(cr3).map(Arrays::toString).forEach(System.out::println);
// [0]
}
public static int[][] centralRegion(int[][] arr) {
if (arr.length == arr[0].length && arr.length % 2 != 0) {
return new int[][]{{arr[arr.length / 2][arr[0].length / 2]}};
} else {
return Arrays.stream(arr, cp(arr.length), arr.length - cp(arr.length))
.map(row -> Arrays
.stream(row, cp(row.length), row.length - cp(row.length))
.toArray())
.toArray(int[][]::new);
}
}
public static int cp(int length) {
return length / 2 - length % 2 == 0 ? 0 : 1;
}
public static int maxValue(int[][] arr) {
return Arrays.stream(arr).flatMapToInt(Arrays::stream).max().getAsInt();
}

How to populate a 2d array with values from a 1d array?

I have a single array populated with some values that I receive from another method, and I want to populate a bidimensional array with values from the first, example:
int[] singleArray; // there's no values here to demonstrate,
// let's think that's populated
int[][] bidimArray = new int[80][80];
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
for (int x = 0; x < singleArray.length; x++) {
bidimArray[i][j] = singleArray[x];
}
}
}
I thought in the solution above, besides it seems very ugly solution, it only saves the last position of singleArray in bidimArray[][]. May anyone help me, please?
There is no need for the third for loop here. This is where you went wrong. The change to your code is to simply increment x for every value entered into the new 2D array and omitting the third for loop.
int[] singleArray;
int[][] bidimArray = new int[80][80];
int x = 0;
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
bidimArray[i][j] = singleArray[x];
x++;
}
}
You can also combine the two inner lines in the loop like this:
bidimArray[i][j] = singleArray[x++];
As pointed out in the comments, you should not hard code array sizes. For your approach, you will have to make sure that the singleArray contains at least 80*80 elements. If this is not given, you should make sure to check that constraint beforehand.
Circular populating of a 2d array 8x7 with values from a 1d array 6. It works the same with larger and smaller arrays regardless of size:
int[] arr1 = {1, 2, 3, 4, 5, 6};
int m = 8;
int n = 7;
int[][] arr2 = IntStream.range(0, m)
.mapToObj(i -> IntStream.range(0, n)
.map(j -> arr1[(j + i * n) % arr1.length])
.toArray())
.toArray(int[][]::new);
// output
Arrays.stream(arr2).map(Arrays::toString).forEach(System.out::println);
[1, 2, 3, 4, 5, 6, 1]
[2, 3, 4, 5, 6, 1, 2]
[3, 4, 5, 6, 1, 2, 3]
[4, 5, 6, 1, 2, 3, 4]
[5, 6, 1, 2, 3, 4, 5]
[6, 1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 1]
[2, 3, 4, 5, 6, 1, 2]
See also: Copying a 1d array to a 2d array

Modifying a 2D array using a nested for loop

I am trying to print out the 'middle' of the 2D array (a). For example, for given arrays in my code, I would like to print:
[3,4,5,6]
[4,5,6,7]
However I was only able to print out the 'middle' values. I would like to modify the 2D array (a) in the method inner and print it in main instead, and not use System.out.println in the nested for loop. How would I go about doing this?
Here is my code:
public static int[][] inner(int[][] a) {
int rowL = a.length - 1;
int colL = a[1].length - 1;
for (int row = 1; row < rowL; row++) {
for (int col = 1; col < colL; col++) {
//System.out.print(a[row][col]);
a = new int[row][col];
}
System.out.println();
}
return a;
}
public static void main(String[] args) {
int[][] a = {
{1, 2, 3, 4, 5, 6},
{2, 3, 4, 5, 6, 7},
{3, 4, 5, 6, 7, 8},
{4, 5, 6, 7, 8, 9}};
for (int[] row : a) {
System.out.println(Arrays.toString(row));
}
System.out.println();
for (int[] row : inner(a)) {
System.out.println(Arrays.toString(row));
}
}
Create a new array outside the loop and then fill that array inside the loop by translating the indices between the two arrays:
public static int[][] inner (int[][] a) {
int rowL = a.length - 1;
int colL = a[1].length -1;
int[][] ret = new int[rowL - 1][colL - 1];
for (int row = 1; row < rowL; row++) {
for (int col = 1; col < colL ; col++) {
ret[row - 1][col - 1] = a[row][col];
}
}
return ret;
}
If you just want to print the middle values (my definition for this code example is: middle = full array minus first and last element), you can make use of a StringBuilder:
public static void main(String[] args) {
int[][] a = {
{ 1, 2, 3, 4, 5, 6 },
{ 2, 3, 4, 5, 6, 7 },
{ 3, 4, 5, 6, 7, 8 },
{ 4, 5, 6, 7, 8, 9 }
};
for (int[] b : a) {
// create a String output for each inner array
StringBuilder outputBuilder = new StringBuilder();
// append an introducing bracket
outputBuilder.append("[");
// make the values to be printed ignore the first and last element
for (int i = 1; i < b.length - 1; i++) {
if (i < b.length - 2) {
/*
* append a comma plus whitespace
* if the element is not the last one to be printed
*/
outputBuilder.append(b[i]).append(", ");
} else {
// just append the last one without trailing comma plus whitespace
outputBuilder.append(b[i]);
}
}
// append a closing bracket
outputBuilder.append("]");
// print the result
System.out.println(outputBuilder.toString());
}
}
The output will be
[2, 3, 4, 5]
[3, 4, 5, 6]
[4, 5, 6, 7]
[5, 6, 7, 8]
You can use Arrays.stream(T[],int,int) method to iterate over a given range of an array:
int[][] arr = {
{1, 2, 3, 4, 5, 6},
{2, 3, 4, 5, 6, 7},
{3, 4, 5, 6, 7, 8},
{4, 5, 6, 7, 8, 9}};
int[][] middle = Arrays.stream(arr, 1, arr.length - 1)
.map(row -> Arrays.stream(row, 1, row.length - 1)
.toArray())
.toArray(int[][]::new);
// output
Arrays.stream(middle).map(Arrays::toString).forEach(System.out::println);
[3, 4, 5, 6]
[4, 5, 6, 7]

How to remove a row from a 2d array?

I have a simple array, sort of like this:
1 2 3 4 5 6 7 8 9
6 2 7 2 9 6 8 10 5
2 6 4 7 8 4 3 2 5
9 8 7 5 9 7 4 1 10
5 3 6 8 2 7 3 7 2
So, let's call this matrix[5][9]. I wish to now remove every row within this matrix that contains a certain value, in this case 10, so I am left with...
1 2 3 4 5 6 7 8 9
2 6 4 7 8 4 3 2 5
5 3 6 8 2 7 3 7 2
Here's a sample class you can run that I believe does what you're looking for. Removing rows from 2D arrays is tricky business because like #KalebBrasee said, you can't really "remove" them, but rather you have to make a whole new 2D array instead. Hope this helps!
import java.util.ArrayList;
import java.util.List;
public class Matrix {
private double[][] data;
public Matrix(double[][] data) {
int r = data.length;
int c = data[0].length;
this.data = new double[r][c];
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
this.data[i][j] = data[i][j];
}
}
}
/* convenience method for getting a
string representation of matrix */
public String toString() {
StringBuilder sb = new StringBuilder(1024);
for (double[] row : this.data) {
for (double val : row) {
sb.append(val);
sb.append(" ");
}
sb.append("\n");
}
return (sb.toString());
}
public void removeRowsWithValue(final double value) {
/* Use an array list to track of the rows we're going to want to
keep...arraylist makes it easy to grow dynamically so we don't
need to know up front how many rows we're keeping */
List<double[]> rowsToKeep = new ArrayList<double[]>(this.data.length);
for (double[] row : this.data) {
/* If you download Apache Commons, it has built-in array search
methods so you don't have to write your own */
boolean found = false;
for (double testValue : row) {
/* Using == to compares doubles is generally a bad idea
since they can be represented slightly off their actual
value in memory */
if (Double.compare(value, testValue) == 0) {
found = true;
break;
}
}
/* if we didn't find our value in the current row,
that must mean its a row we keep */
if (!found) {
rowsToKeep.add(row);
}
}
/* now that we know what rows we want to keep, make our
new 2D array with only those rows */
this.data = new double[rowsToKeep.size()][];
for (int i = 0; i < rowsToKeep.size(); i++) {
this.data[i] = rowsToKeep.get(i);
}
}
public static void main(String[] args) {
double[][] test = {
{1, 2, 3, 4, 5, 6, 7, 8, 9},
{6, 2, 7, 2, 9, 6, 8, 10, 5},
{2, 6, 4, 7, 8, 4, 3, 2, 5},
{9, 8, 7, 5, 9, 7, 4, 1, 10},
{5, 3, 6, 8, 2, 7, 3, 7, 2}};
//make the original array and print it out
Matrix m = new Matrix(test);
System.out.println(m);
//remove rows with the value "10" and then reprint the array
m.removeRowsWithValue(10);
System.out.println(m);
}
}
Use System.arraycopy or use java.util.List instead of arrays. ArrayList has fast access to random elements and a slow remove method, it's the opposite with LinkedList. You have to choose for yourself.
At the and you have to recreate the array and discard the old one. Changing the dimension of an existing array is not possible - if want this type of datastructure, then you should build the matrix based on Collections (ArrayList<ArrayList<Double>>), there you can remove a row easily.
Back to arrays - the idea is to collect all rows (double[] arrays) that you want to keep, create a result array with those rows and replace the old one with the new on on Matrix:
public void doSomethingWith(Matrix in) {
List<double[]> survivingRows = new ArrayList<double[]>();
for (double[] row:in.getRows()) {
if (isAGoodOne(row)) {
survivingRows.add(row);
}
}
double[][] result = new double[survivingRows][];
for (int i = 0; i < result.length; i++) {
result[i] = survivingRows.get(i);
}
in.setArray(result);
}
You can't remove elements from the Java built-in array data structure. You'll have to create a new array that has a length one less than the first array, and copy all the arrays into that array EXCEPT the one you want to remove.
My java syntax is a little rusty, but the following, if treated as pseudocode will work
public Matrix removeRows(Matrix input) {
int[][] output = new int[input.numRows][input.numColumns]();
int i = 0;
for (int[] row : input.rows()) { // Matrix.rows() is a method that returns an array of all the rows in the matrix
if (!row.contains(10)) {
output[i] = row;
}
}
return output
My take:
import java.util.Arrays;
public class RemoveArrayRow {
private static <T> T[] concat(T[] a, T[] b) {
final int alen = a.length;
final int blen = b.length;
if (alen == 0) {
return b;
}
if (blen == 0) {
return a;
}
final T[] result = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), alen + blen);
System.arraycopy(a, 0, result, 0, alen);
System.arraycopy(b, 0, result, alen, blen);
return result;
}
public static void main(String[] args) {
double[][] d = { {11, 2, 3, 4, 5, 6, 7, 8, 9, 0},
{12, 2, 3, 4, 5, 6, 7, 8, 9, 1},
{13, 2, 3, 4, 5, 6, 7, 8, 9, 2},
{14, 2, 3, 4, 5, 6, 7, 8, 9, 3},
{15, 2, 3, 4, 5, 6, 7, 8, 9, 4} };
//remove the fourth row:
// (1)
double[][] d1 = concat(Arrays.copyOf(d, 3), Arrays.copyOfRange(d, 4, 5));
// (2)
double[][] d2 = new double[d.length - 1][d[0].length];
System.arraycopy(d, 0, d2, 0, 3);
System.arraycopy(d, 4, d2, 3, 1);
System.out.print(d1.length);
System.out.print(d2.length);
}
}
(1)
If you exclude the concat() function used for concatenating two arrays, it's done in one line:
double[][] d1 = concat(Arrays.copyOf(d, 3), Arrays.copyOfRange(d, 4, 5));
See this question as well. That's where the code for the concat() function comes from.
(2)
This method is faster and only uses already available functions.
Since it cannot avoid creating new 2D array to contain the after-removed data, firstly, create a new 2D int[][] b with same dimension as a[][]. secondly, loop through a[][], assign a to b and move b row up when a contain specific value. and sanity check the last row, which can contain specific data.
public static int[][] remove(int[][] a, int v) {
int r = a.length;
int c = a[0].length;
int[][] b = new int[r][c];
int red = 0;
boolean s = false;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
b[i - red][j] = a[i][j];
if (a[i][j] == v) {
red += 1;
if(i==r-1){
s = true;
}
break;
}
}
}
//check last row
if(s){
for(int i = r-red;i <r-red +1; i++ )
for (int j = 0; j<c; j++){
b[i][j] = 0;
}
}
return b;
}
public static void main(String[] args){
int[][] a = { {1, 2, 3, 4, 5, 6, 7, 8, 1},
{6, 2, 7, 2, 9, 6, 8, 10, 5},
{2, 6, 4, 7, 8, 4, 2, 2, 5},
{9, 8, 7, 5, 9, 7, 4, 1, 1},
{5, 3, 6, 8, 2, 7, 3, 1, 1} };
print(remove(a, 10));
}
public static void print(int[][] a) {
int r = a.length;
int c = a[0].length;
int red = 0;
for (int i = 0; i < r; i++) {
System.out.printf("\nrow %d, \n", i);
for (int j = 0; j < c; j++) {
System.out.printf("%d, ", a[i][j]);
}
}
}
This may not be an exact solution but a concept of how you can achieve it using System.arraycopy.
In the example below, I want to copy all the rows except the first row. In your case, you can skip those rows which contain 10.
String[][] src = getSheetData(service, spreadSheetId, range);
String[][] dest = new String[src.length-1][src[0].length];
for (int i = 1; i < src.length; i++) {
System.arraycopy(src[i], 0, dest[i-1], 0, src[0].length-1);
}
Reference: https://docs.oracle.com/javase/6/docs/api/java/lang/System.html#arraycopy%28java.lang.Object,%20int,%20java.lang.Object,%20int,%20int%29
You can use IntStream.noneMatch method for this purpose:
int[][] arr1 = {
{1, 2, 3, 4, 5, 6, 7, 8, 9},
{6, 2, 7, 2, 9, 6, 8, 10, 5},
{2, 6, 4, 7, 8, 4, 3, 2, 5},
{9, 8, 7, 5, 9, 7, 4, 1, 10},
{5, 3, 6, 8, 2, 7, 3, 7, 2}};
int[][] arr2 = Arrays.stream(arr1)
.filter(row -> Arrays.stream(row).noneMatch(i -> i == 10))
.toArray(int[][]::new);
// output
Arrays.stream(arr2).map(Arrays::toString).forEach(System.out::println);
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 6, 4, 7, 8, 4, 3, 2, 5]
[5, 3, 6, 8, 2, 7, 3, 7, 2]

Categories