Writing a toString method for 2D arrays - java

I have some code for a 2D array but I don't want spaces at the end of each row before I start a new row. For some reason, I can't find where I'm messing up because a space is being put at the end of each row. Basically what I'm trying to do is input a 2D array and the output should make it look the same as the input, except for the {}'s and it'll be a string. For example,
Input:
{1, 2, 3},
{4, 5, 6};
Output:
1 2 3
4 5 6
public class Matrix {
// the dimensions of the matrix
private int numRows;
private int numColumns;
// the internal storage for the matrix elements
private int data[][];
/**
* #param d - the raw 2D array containing the initial values for the Matrix.
*/
public Matrix(int d[][])
{
// d.length is the number of 1D arrays in the 2D array
numRows = d.length;
if(numRows == 0)
numColumns = 0;
else
numColumns = d[0].length; // d[0] is the first 1D array
// create a new matrix to hold the data
data = new int[numRows][numColumns];
// copy the data over
for(int i=0; i < numRows; i++)
for(int j=0; j < numColumns; j++)
data[i][j] = d[i][j];
}
/**
* Returns a String representation of this Matrix.
*/
#Override // instruct the compiler that we intend for this method to override the superclass' (Object) version
public String toString() {
// TODO: replace the below return statement with the correct code.
String arrString = "";
for(int i = 0; i < data.length; i++) {
for(int j = 0; j < data[i].length; j++) {
arrString += data[i][j] + " ";
}
arrString += "\n";
}
return arrString;
}

Next time please post a runnable example.
Your problem was that you always added a space after the item, no matter if it was the last one in the line. I now check that with a conditional + (j == data[i].length - 1 ? "" : " ");
Hint: It's not good to concatenate Strings. Use StringBuilder for better performance an memory usage. I added a second method toString2() to show how it's done.
package stackoverflow;
public class Matrix {
// the dimensions of the matrix
private final int numRows;
private int numColumns;
// the internal storage for the matrix elements
private final int data[][];
/**
* #param d - the raw 2D array containing the initial values for the Matrix.
*/
public Matrix(final int d[][]) {
// d.length is the number of 1D arrays in the 2D array
numRows = d.length;
if (numRows == 0)
numColumns = 0;
else
numColumns = d[0].length; // d[0] is the first 1D array
// create a new matrix to hold the data
data = new int[numRows][numColumns];
// copy the data over
for (int i = 0; i < numRows; i++)
for (int j = 0; j < numColumns; j++)
data[i][j] = d[i][j];
}
/**
* Returns a String representation of this Matrix.
*/
#Override // instruct the compiler that we intend for this method to override the superclass' (Object) version
public String toString() {
// TODO: replace the below return statement with the correct code.
String arrString = "";
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
arrString += data[i][j] + (j == data[i].length - 1 ? "" : " ");
}
arrString += "\n";
}
return arrString;
}
public String toString2() {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
sb.append(data[i][j] + (j == data[i].length - 1 ? "" : " "));
}
sb.append("\n");
}
return sb.toString();
}
public static void main(final String[] args) {
final int[][] arr = new int[2][3];
arr[0][0] = 4;
arr[0][1] = 6;
arr[0][2] = 8;
arr[1][0] = 8;
arr[1][1] = 16;
arr[1][2] = 23;
final Matrix m = new Matrix(arr);
System.out.println("Matrix:\n" + m);
System.out.println("Matrix 2:\n" + m.toString2());
}
}
Output:
Matrix:
4 6 8
8 16 23
Matrix 2:
4 6 8
8 16 23

The Answer by JayC667 seems to correctly address your Question.
Stream, lambda, & method reference
For fun, here is an alternative approach using stream, lambda, and method reference.
Define the array.
int[][] input = { { 1 , 2 , 3 } , { 4 , 5 , 6 } }; // Declaration, initialization.
Make a stream where each element is a row, an array of int values, from your two-dimensional array.
For each of those rows, each being a int[], make a stream of its int primitive values (an IntStream), convert each primitive to an Integer object (boxing), call each Integer object’s toString method to generate a piece of text. Collect those pieces of text by joining them into a longer String with a SPACE character as a delimiter.
So we have transformed each row into a String. Collect all those strings together, with a LINE FEED character as the delimiter. Then, we are done, with a single String object as a result.
All that work, in a single line of code!
String result =
Arrays
.stream( input ) // A series of integer arrays, etc element being a int[].
.map( // Convert each integer array into something else, a `String` object.
( int[] row ) -> Arrays.stream( row ).boxed().map( Object :: toString ).collect( Collectors.joining( " " ) )
)
.collect( Collectors.joining( "\n" ) ); // Join each row of text with the next, using Linefeed as delimiter.
Results.
1 2 3
4 5 6

Here is one way to return a formatted 2D array based on the anticipated width of the values.
%nd - specifies a field width of n digits, right aligned.
%-nd - specifies a field width of n digits, left aligned (would have spaces at end of line).
fields will be filled in with spaces where necessary.
public class TwoDtoString {
int[][] mat = { { 11, 222, 3333 }, { 433, 53, 633 }, { 73, 8, 9333 } };
static String FORMAT = "%5d"; // 5 digit field, right aligned.
public static void main(String[] args) {
TwoDtoString tos = new TwoDtoString();
System.out.println(tos.toString());
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (int[] row : mat) {
sb.append(FORMAT.formatted(row[0]));
for (int i = 1; i < row.length; i++) {
sb.append(FORMAT.formatted(row[i]));
}
sb.append("\n");
}
return sb.toString();
}
}
prints
11 222 3333
433 53 633
73 8 9333

Related

How to find largest 10 elements in multi dimentional array?

I hope this will print one largest value. but it need 10 largest elements in an 3D array.
public class foo{
Public static void main(String[] args){
int row,col,dep=3;
int[][][] value=new int[row][col][dep];
/* insert the value from user or initialize the matrix*/
int max=0;
for(row=0;row<3;row++)
for(col=0;col<3;col++)
for(dep=0;dep<3;dep++)
if(value[row][col][dep]>max)
max=value[row][col][dep];
System.out.println(max);
}
}
You can add all integers into a List<Integer>, sort it, and then get the X max numbers of it:
public class foo {
public static void main(String[] args) {
int row = 3, col = 3, dep = 3;
int[][][] value = new int[row][col][dep];
value[1][2][1] = 10;
value[1][0][1] = 15;
List<Integer> listWithAll = new ArrayList<>();
/* insert the value from user or initialize the matrix*/
int max = 0;
for (row = 0; row < 3; row++)
for (col = 0; col < 3; col++)
for (dep = 0; dep < 3; dep++)
listWithAll.add(value[row][col][dep]);
listWithAll.sort(Collections.reverseOrder());
for (int i = 0; i < 10; i++) {
System.out.println(listWithAll.get(i));
}
}
}
which prints:
15 10 0 0 0 0 0 0 0 0
or using Java 8 streams only:
List<Integer> max10 = listWithAll.stream()
.sorted(Collections.reverseOrder())
.limit(10)
.collect(Collectors.toList());
max10.forEach(System.out::println);
Here is a way to do it with streams. I used a complete 2 x 2 x 2 array to make it easier but it would work with any int[][][] array. Instead of using nested loops, I just flatMapped the arrays.
Initialize the array.
int[][][] v = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};
Now get the top4 values (or top N values) and put them in a list.
int top4 = 4;
List<Integer> top4Max =
Arrays.stream(v).flatMap(Arrays::stream).flatMapToInt(
Arrays::stream).boxed().sorted(
Comparator.reverseOrder()).limit(top4).collect(
Collectors.toList());
System.out.println(top4Max);
Prints
8 7 6 5
The Arrays.stream strips one level of array. The flatMap takes those and further flattens them into a single dimenion array. The flatMapToInt flattens that into a stream of ints where they are sorted and processed into a limited collection.
If required, you could also put them in an array instead of a list.
Alternatively, one could create a small array and use it as with a normal findmax function.
public class Array_3D {
public static void main(String[] args) {
int row = 3, col = 3, dep = 3;
int[][][] value = new int[row][col][dep];
value[1][2][1] = 10;
value[1][0][1] = 15;
int[] topten = new int[10]; //array to hold max values
int count = 0;
int candidate = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
for (int k = 0; k < dep; k++) {
if (count < 10) { //start with first ten values
topten[count] = value[i][j][k];
count++;
}
else {
candidate = value[i][j][k];
for (int x = 0; x < 10; x++) { //loop for loading top values
if (candidate > topten[x]) {
topten[x] = candidate;
break; //exit on first hit
}
}
}
}
}
}
for (int i = 0; i < 10; i++) {
System.out.print(topten[i] + " ");
}
System.out.println();
}
}
I don't know which method is faster for large 3D arrays; here we have to run a small loop at every point in the 3D array, vs creating an entirely new list and sorting it. Clearly this wins in memory usage, but not sure about speed. [Edit note this returns an unsorted array of the top ten values as is].

Parse file and splitting individual lines into 2d array

I have one text file in which each String holds one line of numbers say 203 and I have one 2d array int puzzle[][].
The lines of file are in the array list Arraylist<String> lines .The first String from the array list goes into puzzle[0].The second String goes into puzzle[1], etc.
The problem I'm having is that after splitting the lines I cannot convert those numbers into integers because it gives me number format exception for -1 what if I will split that - and 1 as well.
I tried the following and also making deep copy of the string array and then transforming each string into an integer
public void parseFile(ArrayList<String> lines)
{
ArrayList<String> l = lines;
for(int i =0; i<puzzle.length; i++)
puzzle[i][0] = Integer.parseInt(l.get(i).split(""));
}
it should give me 2d array with integers
Here is a method that will take a list of strings made up of single digit numbers and convert the list to a 2d array of int. This code makes no use of Java 8 streams.
public static int[][] parseFile(List<String> lines) {
int[][] result = new int[lines.size()][];
int multiplier = 1;
int counter = 0;
for (String line : lines) {
List<Integer> row = new ArrayList<>();
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (c == '-') {
multiplier = -1;
continue;
}
int n = (int)c - 48;
row.add(n * multiplier);
multiplier = 1;
}
int[] rowArray = new int[row.size()];
for (int j = 0; j < row.size(); j++) {
rowArray[j] = row.get(j);
}
result[counter] = rowArray;
counter++;
}
return result;
}
Below is my test code, execute from main
List<String> list = new ArrayList<>();
list.add("-111");
list.add("2-13");
int[][] result = parseFile(list);
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[i].length; j++) {
System.out.printf("%d ", result[i][j]);
}
System.out.print("\n");
}
Output
-1 1 1
2 -1 3

I created decimal to binary method and I want to use it in 2D array but I can't

I created simple decimal to binary method like this :
public static int[] convertDectoB(int number, int size) {
int binary[] = new int[size];
for (int a = number; a > 0 && size > 0; size--, a = a / 2) {
binary[size - 1] = a % 2;
}
return binary;
}
I asked user to enter numbers like that :
"Enter numbers : "
4-2-7.
The aim is convert these 3 numbers into a binary and print it :
1 0 0
0 1 0
1 1 1
I also created numberFinder method to extract integers into the String that user entered :
public static int[] numberFinder(String numbers, int size) {
int numaraa[] = new int[size];
int a = 0;
for (int i = 0; i < numaraa.length; i++) {
for (; a < numbers.length(); a++) {
if (numbers.charAt(i) == '-')
i++;
else if (a == 0) {
if (Character.isDigit(numbers.charAt(a)))
numaraa[i] += numbers.charAt(a);
}
else {
if (Character.isDigit(numbers.charAt(a)))
numaraa[i] += numbers.charAt(a);
}
}
}
return numaraa;
}
In the end , I created 2D array and I wanna implement these binary values :
for (int i = 0; i < mainarray.length; i++) {
for (int j = 0; j < mainarray[i].length; j++) {
mainarray[i][j] = ?
}
}
}
But I can't implement all binary values for each array block.
If you need to make your own toBinaryString() method there are a lot of examples online, such as borrowing the logic from this answer Print an integer in binary format in Java:
public static String intToString(int number) {
StringBuilder result = new StringBuilder();
for(int i = 2; i >= 0 ; i--) {
int mask = 1 << i;
result.append((number & mask) != 0 ? "1" : "0");
}
return result.toString();
}
Note: I modified this method to only hold 3 digit binary codes, so the highest integer it can convert is 7. However if you want to convert larger integers, say up to 16, or 32, you'll need to increase the counter in the for-loop, which I'll leave that for you to decide.
For each line in the user input, split it on the hyphen character '-':
codes = line.split("-");
ListofCourses.addAll(Arrays.asList(codes));
...
Then call this method on your ListofCourses:
for(int r = 0; r < ListofCourses.size(); r++){
System.out.println(intToString(Integer.parseInt(ListofCourses.get(r))));
}
ListofCourses.clear();
Then should get expected output. Here's demo:
Ron's Copy
Enter 3 collections of course codes one collection per line
4-2-7
Size: 3 Sorted: [4, 2, 7]
100
010
111

Generating 2D double array from text file

I have a text file
0.4658 0 3
0.4095 0 3
0.4594 0 3
0.4297 0 3
0.3963 0 3
0.4232 0 3
0.4633 0 3
0.5384 0 3
0.5042 0 3
0.4328 0 3
that I want to read into a 2D double array that looks like this.
{{0.4658, 0, 3},
{0.4095, 0, 3},
... (and so on)
{0.4328, 0, 3}}
I have the following code:
public static void main(String[] args) throws Exception{
double[][] ref = null;
ref = matrix("data80.in",10,3);
}
public static double[][] matrix(String filename, int size1, int size2) throws Exception {
double[][] matrix = null;
BufferedReader buffer = new BufferedReader(new FileReader(filename));
String line;
int row = 0;
while ((line = buffer.readLine()) != null) {
String[] vals = line.trim().split("\\s+");
if (matrix == null) {
matrix = new double[size1][size2];
}
for (int col = 0; col < size1; col++) {
matrix[row][col] = Double.parseDouble(vals[col]);
}
row++;
}
buffer.close();
return matrix;
}
But it keeps giving me an outOfBounds exception, and I don't know where I am going wrong. Please help. If anyone has more efficient solutions as well to my problem it would be helpful
It's because of the following for loop:
for (int col = 0; col < size1; col++) {
matrix[row][col] = Double.parseDouble(vals[col]);
}
We are using size1 whereas we should be using size2, following would work:
for (int col = 0; col < size2; col++) {
matrix[row][col] = Double.parseDouble(vals[col]);
}
Also, there is no need for null check inside the for loop, you can remove it and initialise the array in the beginning, e.g.:
public static double[][] matrix(String filename, int size1, int size2) throws Exception {
double[][] matrix = new double[size1][size2];;
BufferedReader buffer = new BufferedReader(new FileReader(filename));
String line;
int row = 0;
while ((line = buffer.readLine()) != null) {
String[] vals = line.trim().split("\\s+");
for (int col = 0; col < size2; col++) {
matrix[row][col] = Double.parseDouble(vals[col]);
}
row++;
}
buffer.close();
return matrix;
}
You have defined you 2d matrix as
matrix = new double[size1][size2];
meaning there are size1 rows and size2 columns but in following line:
for (int col = 0; col < size1; col++) {
you have used size1. So correction is:
for (int col = 0; col < size2; col++) {
Here is yet another concept as to how you can place the delimited numerical data contained within a text file of any number of rows and any number of columns into a Double data type Two Dimensional Array. All you need to do is pass the path and file name to the method. You can also optionally supply the delimiter used within the file, the method default is a comma (,) delimiter since it is one of the most commonly used. Here is the method:
public static double[][] matrix(String filename, String... delimiterInFile) {
String delimiter = ","; // Default data delimiter in file.
// See if a optional data delimiter is supplied...
if (delimiterInFile.length > 0) { delimiter = delimiterInFile[0]; }
// Catch IO Exceptions
try {
//Place the contents of file into a ArrayList
List<String> list = Files.lines(Paths.get(filename)).collect(Collectors.toList());
// Get the greatest number of delimited columns contiained
// within the ArrayList the whole while ignoring blank lines
// (there could be blank lines in file). Our columns for our
// double 2D Array will be determined from this value. We also
// determine the true number of rows required (remember, no
// blank elements allowed so ArrayList.size() wont be good enough).
int r = 0, c = 0;
for (int i = 0; i < list.size(); i++) {
if (!list.get(i).equals("")) {
int l = list.get(i).split(delimiter).length;
if (l > c) { c = l; }
r++;
}
}
// If we have nothing then the get outta here
// by returning null.
if (r == 0 || c == 0) { return null; }
// Declare and initialize a double data type 2D Array
double[][] array = new double[r][c];
// Fill the double type array...
for (int i = 0; i < list.size(); i++) {
if (!list.get(i).equals("")) {
String[] data = list.get(i).split(delimiter);
for (int j = 0; j < data.length; j++) {
array[i][j] = Double.parseDouble(data[j]);
}
}
}
return array;
} catch (IOException ex) {
// Do what you want with the Exception...
ex.printStackTrace();
return null;
}
}
This method will automatically determine the required number of Rows and Columns for the returned Double data type 2D Array. The method ignores blank file lines so the required Rows needed for the returned Double 2D Array is determined with this in mind. The number of Columns value is determined by iterating through the data lines and detecting which data line contains the most delimited data. That column count is used for the entire 2D Array. This means then that file data lines which contain less columns will have their remaining Array Elements filled with a 0.0 double type value.
The optional delimiter that can be passed to this method can be any string or a RegEx (Regular Expression) string, for example: " " or "\\s+" or "," or ", " or "\t", etc.
This method will also throw an IO Exception should there be a problem accessing the supplied data file.
With the data file schema you provided:
0.4658 0 3
0.4095 0 3
0.4594 0 3
0.4297 0 3
0.3963 0 3
0.4232 0 3
0.4633 0 3
0.5384 0 3
0.5042 0 3
0.4328 0 3
and let's assume this file is named data.txt which is in your classpath, you might use this method like this:
double[][] myData = matrix("data.txt", "\\s+");
for (int i = 0; i < myData.length; i++) {
String strg = "";
for (int j = 0; j < myData[0].length; j++) {
strg+= myData[i][j] + " ";
}
System.out.println(strg);
}
Keep in mind, this is not a method I would recommend for really large data files (Hundreds of thousands of lines).

converting a matrix to string

I am working on writing a matrix, but unfortunately I am stuck with the output.
Instead of showing a matrix, it shows me something like:
actual matrix is
Matrix#512fb063
I need to convert the matrix to a string so that the output will look like this:
expected the matrix:
3 8 72
4 6 60
253 2 1
the code that I've written is this:
import java.util.Random;
final public class Matrix {
private final int size1; // number of rows
private final int size2; // number of columns
private final int[][] data; // M-by-N array
// create size1-by-size2 matrix of 0's
public Matrix(int size1, int size2) {
this.size1 = size1;
this.size2 = size2;
data = new int[size1][size2];
}
// create matrix based on 2d array
public Matrix(int[][] data) {
size1 = data.length;
size2 = data[0].length;
this.data = new int[size1][size2];
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
this.data[i][j] = data[i][j];
}
// creates and returns a random size1-by-size1 matrix with values between 0 and 255
public String toString(int size1, int size2) {
Matrix A = new Matrix(size1, size2);
String str = " ";
final int white = 0;
final int black = 255;
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
{
A.data[i][j] = white + (int)(Math.random() * ((black ) ));
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
if (i==size1 &&j==size2) str = (A.data[i][j]+"\n");
}
return str;
}
You need to override the public String toString() function. What you are doing now is creating a new function called String toString(int size1, int size2).
Your new function is not called when writing:
System.out.println(myMatrix);
You could either do:
System.out.println(myMatrix.toString(2, 2));
or override the default toString() function.
So the following code should work:
#Override
public String toString() {
Matrix A = new Matrix(size1, size2);
String str = " ";
final int white = 0;
final int black = 255;
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
{
A.data[i][j] = white + (int)(Math.random() * ((black ) ));
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
if (i==size1 &&j==size2) str = (A.data[i][j]+"\n");
}
return str;
}
where size1 and size2 are variables in the class.
Your output of actual matrix is Matrix#512fb063 is actually the memory address in Java that your instance of the class Matrix sits in. That's because your program doesn't know how to "print" this class - it doesn't magically know that you want a row/column representation of it.
You've got a number of options:
Your toString(int size1, int size2) is perfect. So when you want to print your matrix, you can go System.out.println(someMatrix.toString(2,2)) will work where someMatrix is an instance of your Matrix class.
If you want it to work properly by you just going System.out.println(someMatrix) then you will need to overwrite your Matrix class' toString() function. You -almost- did that in your toString(int size1, int size2) function but it didn't work because it needs to match exactly the parameters, ie: toString() should take 0 parameters. You will need to write a toString() method which can then call your toString(int size1, int size2)
Somehow you get the hashcode. Maybe you can use http://math.nist.gov/javanumerics/jama/doc/ matrix implementation.
I think this line is not working
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
Don't you get an IndexOutOfBoundexception? Anyway A.data[i][j+1] is always empty within the loop. By the way, Variables in Java are always lower case.
You can simply do :
#Override
public String toString()
{
return toString(size1,size2);
}
Edit : If you want to reflect the real content of your current Matrix :
#Override
public String toString()
{
StringBuilder sbResult = new StringBuilder();
for(int i = 0; i < size1;i++)
{
for(int j = 0; j < size2;j++)
{
sbResult.append(A.data[i][j]);
sbResult.append("\t");
sbResult.append(A.data[i][j+1]);
if(i == size1 && j == size2)
{
sbResult.append("\n");
}
}
}
return sbResult.toString();
}

Categories