I have a method attempting to transpose a ArrayList containing an ArrayList of string, called matrix and return the new array.
I found Transposing Values in Java 2D ArrayList, but it looks like it's for Arrays and not ArrayLists. My 2D array is of unknown dimensions, either rectangular or possibly irregular (but never square).
My idea was to read each inner array, and append the items to the inner arrays of the outgoing matrix.
public static ArrayList<ArrayList<String>> transpose (ArrayList<ArrayList<String>> matrixIn){
ArrayList<ArrayList<String>> matrixOut = new ArrayList<>();
//for each row in matrix
for (int r = 0; r < matrixIn.size(); r++){
ArrayList<String> innerIn = matrixIn.get(r);
//for each item in that row
for (int c = 0; c < innerIn.size(); c++){
//add it to the outgoing matrix
//get matrixOut current value
ArrayList<String> matrixOutRow = matrixOut.get(c);
//add new one
matrixOutRow.add(innerIn.get(c));
//reset to matrixOut
matrixOut.set(c,matrixOutRow);
}
}
return matrixOut;
}
I'm getting an "IndexOutOfBoundsException: Index: 0, Size: 0" error at
//get matrixOut[v]
ArrayList<String> matrixOutRow = matrixOut.get(v);
What am I doing wrong with this thing?
Assumption: Each inner list has same no of elements. This could help you.
public static List<List<String>> transpose(ArrayList<ArrayList<String>> matrixIn) {
List<List<String>> matrixOut = new ArrayList<List<String>>();
if (!matrixIn.isEmpty()) {
int noOfElementsInList = matrixIn.get(0).size();
for (int i = 0; i < noOfElementsInList; i++) {
List<String> col = new ArrayList<String>();
for (List<String> row : matrixIn) {
col.add(row.get(i));
}
matrixOut.add(col);
}
}
return matrixOut;
}
Answering my own question here. This is what I'm now doing:
public static ArrayList<ArrayList<String>> transpose (ArrayList<ArrayList<String>> matrixIn){
ArrayList<ArrayList<String>> matrixOut = new ArrayList<>();
int rowCount = matrixIn.size();
int colCount = 0;
//find max width
for(int i = 0; i < rowCount; i++){
ArrayList<String> row = matrixIn.get(i);
int rowSize = row.size();
if(rowSize > colCount){
colCount = rowSize;
}
}
//for each row in matrix
for (int r = 0; r < rowCount; r++){
ArrayList<String> innerIn = matrixIn.get(r);
//for each item in that row
for (int c = 0; c < colCount; c++){
//add it to the outgoing matrix
//get matrixOut[c], or create it
ArrayList<String> matrixOutRow = new ArrayList<>();
if (r != 0) {
try{
matrixOutRow = matrixOut.get(c);
}catch(java.lang.IndexOutOfBoundsException e){
System.out.println("Transposition error!\n"
+ "could not get matrixOut at index "
+ c + " - out of bounds" +e);
matrixOutRow.add("");
}
}
//add innerIn[c]
try{
matrixOutRow.add(innerIn.get(c));
}catch (java.lang.IndexOutOfBoundsException e){
matrixOutRow.add("");
}
//reset to matrixOut[c]
try {
matrixOut.set(c,matrixOutRow);
}catch(java.lang.IndexOutOfBoundsException e){
matrixOut.add(matrixOutRow);
}
}
}
return matrixOut;
}
I can't assume smooth arrays and I want to still return a nested ArrayList. So now I'm just finding the maximum dimensions and catching all of the out of bounds errors by adding "".
I'm sure there's a cleaner way, but this seems to be working.
Related
I currently have a text file in the format
matrix
row
a
b
c
row
d
e
f
row
g
h
i
row
j
k
l
matrix
row
m
n
o
p
q
row
r
s
t
u
v
I would like to convert this into two integer matrices (stored as 2 2D arrays), in the format
a b c
d e f
g h i
j k l
and
m n o p q
r s t u v
So far, I have created a Scanner object of the file and put each line in a text array:
Scanner sf = new Scanner(new File("C:\\textfiles\\matrices.txt"));
int maxIndex = -1;
String text[] = new String[10000]; // I added more than necessary for safety
while (sf.hasNext()){
maxIndex++;
text[maxIndex] = sf.nextLine();
}
sf.close();
This way, the text file is now contained in a string array, where each line is a new element of the array. Right now, I would like to partition the array into two arrays with each array being the matrices. How should I continue? (note: I am a total beginner and desire answers that are simple (no arraylist, hashmap, etc., and that's why this question is not a duplicate of How to read two matrices from a txt file in java because it uses BufferedReader, and there are other potential duplicate questions, so I would like to clear this up)
What I currently have after the top:
int counter = 0;
int iCounter = 0; // row
int jCounter = 0; // column
int matrix1[][];
int matrix2[][];
while (counter < maxIndex){
if (counter = 0)
{
\\not yet written...
}
\\not yet written...
}
As #Rob said, it's really cumbersome to do this without dynamic data structures such as ArrayList's. But nevertheless, here's a code that does your job (considering you have only two matrices), without using any List's:
int counter = 0;
int iCounter = 0; // row
int jCounter = 0; // column
int matrix1[][];
int matrix2[][];
int rowSize = 0, numberOfRows = 0;
counter = 2;
while (!text[counter].equals("row") && !text[counter].equals("matrix")) {
counter++;
rowSize++;
}
//now we have the row size
numberOfRows = 1;
while (!text[counter].equals("matrix")) {
if (text[counter].equals("row"))
numberOfRows++;
counter++;
}
//now we have the total number of rows
matrix1 = new int[numberOfRows][rowSize];
counter = 2; //to start from the first matrix
//now counter should point to the first row of the first matrix
while (!text[counter].equals("matrix")) {
jCounter = 0;
while (!text[counter].equals("row")
&& !text[counter].equals("matrix")) {
matrix1[iCounter][jCounter++] = Integer.parseInt(text[counter]);
//supposing your input is Integers, otherwise, you can change
//it to the corresponding type (i.e. Long, Double, etc)
counter++;
}
iCounter++;
if (!text[counter].equals("matrix"))
counter++;
}
//now we finished with the first matrix, and the counter points to
//the first "row" of the second matrix, so we do the same thing again
rowSize = 0;
numberOfRows = 0;
int startOfSecondMatrix = counter + 2; //save this for later
counter += 2; // so that counter points to the first number
while (counter < text.length && !text[counter].equals("row")) {
counter++;
rowSize++;
}
numberOfRows = 1;
while (counter < text.length) {
if (text[counter].equals("row"))
numberOfRows++;
counter++;
}
matrix2 = new int[numberOfRows][rowSize];
counter = startOfSecondMatrix;
iCounter = 0;
while (counter < text.length) {
jCounter = 0;
while (counter < text.length && !text[counter].equals("row")) {
matrix2[iCounter][jCounter++] = Integer.parseInt(text[counter]);
counter++;
}
iCounter++;
counter++;
}
For each matrix we perform the same operations:
-We first go through the matrix to count its size to be able to initialize it, after that, we go row by row, and parse each number.
You might as well put all the work for one matrix into a function (and take care of the bounds) and call it as long you still have more matrices.
This does what you want. Unfortunately doing this with 2D arrays is considerably harder since once you set the size of an array its difficult to manage changing it. Therefore using ArrayList is much easier.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Main {
public static final String MATRIX = "matrix";
public static final String ROW = "row";
public static void main(String[] args) throws FileNotFoundException {
// Use correct file name here
Scanner sf = new Scanner(new File("matrices.txt"));
// This is a List of 2D Lists
List<List<List<String>>> matrices = new ArrayList<>();
// easier to process lines as we're reading them in so we
// only iterate over the file once
while (sf.hasNext()) {
boolean hasBeenProcessed = false;
String inputValue = sf.nextLine();
switch (inputValue) {
case MATRIX:
ArrayList<List<String>> matrix = new ArrayList<>();
matrices.add(matrix);
hasBeenProcessed = true;
break;
case ROW:
List<List<String>> currentMatrix = getMatrixBeingProcessed(matrices);
currentMatrix.add(new ArrayList<String>());
hasBeenProcessed = true;
break;
}
if (!hasBeenProcessed) {
List<List<String>> currentMatrix = getMatrixBeingProcessed(matrices);
List<String> currentRow = getCurrentRow(currentMatrix);
currentRow.add(inputValue);
}
}
// Print out the results:
int i = 1;
for (List<List<String>> matrix : matrices) {
System.out.println("Matrix " + i);
for (List<String> row : matrix) {
for (String element : row) {
System.out.print(element + " "); // no newline until end of the row
}
System.out.println(); // new line
}
i++;
System.out.println(); // new line
}
}
private static List<String> getCurrentRow(List<List<String>> currentMatrix) {
int lastRow = currentMatrix.size() - 1;
return currentMatrix.get(lastRow);
}
private static List<List<String>> getMatrixBeingProcessed(List<List<List<String>>> matrices) {
int lastMatrix = matrices.size() - 1;
List<List<String>> currentMatrix = matrices.get(lastMatrix);
return currentMatrix;
}
}
Output:
Matrix 1
a b c
d e f
g h i
j k l
Matrix 2
m n o p q
r s t u v
Process finished with exit code 0
Since you don't want to use List and arrays can't be resized once initialized, this is not easy.
There are two ways: Read the file and initialize arrays knowing the size (as #Maaddy posted) or 'resizing' arrays. That's not possible but it is if you use Arrays.copyOf() so you can create a new array.
The idea is create a 'tridimensional' array where you can store: matrix, row and column; and then start to read the file.
Every time you find a word the entire array will be updated creating a new array with one length more.
If the word is 'matrix' the extra length will be added to the first position (the position who 'store' the matrix)
If the word is 'row' then the space will be added for the current matrix. So in this way, the current matrix will have one more array where store the column values.
If the word is other then is a value for the column. The column is resized and added to the correct position.
Note that if a word 'matrix' or 'row' is found, the new array is initialized with no length. This is because will be resized later, when is necessary.
The code is as follows:
//Initialize array with no positions
String[][][] arrays = new String[0][0][0];
Scanner sf = new Scanner(new File("path/matrices.txt"));
int matrix = -1;
int row = -1;
int column = -1;
while (sf.hasNext()){
String line = sf.nextLine();
if(line.equals("matrix")) {
//'Resize' array: Create new array with 1 more length and old data
arrays = Arrays.copyOf(arrays, arrays.length + 1);
//Start new matrix
arrays[++matrix] = new String[0][0];
row = -1;
column = -1;
}else if(line.equals("row")) {
//'Resize' matrix: Create a new array with 1 more length and old data
arrays[matrix] = Arrays.copyOf(arrays[matrix], arrays[matrix].length+1);
row++;
arrays[matrix][row] = new String[0];
column = -1;
}else{
//'Resize' matrix
column++;
arrays[matrix][row] = Arrays.copyOf(arrays[matrix][row], arrays[matrix][row].length+1);
arrays[matrix][row][column] = line;
}
}
sf.close();
//Print result
for(int i = 0 ; i < arrays.length; i++) {
System.out.println("Matrix "+i);
for(int j = 0; j < arrays[i].length; j++ ) {
for(int k = 0; k < arrays[i][j].length; k++) {
System.out.print(arrays[i][j][k]+ " ");
}
System.out.println();
}
System.out.println();
}
And the result is:
Matrix 0
a b c
d e f
g h i
j k l
Matrix 1
m n o p q
r s t u v
I am trying to display the contents of an array after iterating through rows and columns of a JTable. I tried Arrays.toString(myTwoDimensionalArrayVariable) but it won't display the string values.
My goal is to check duplicates for every column per row of a destination JTable when user tries to add row values from a source JTable that's why I want to display the contents of the array.
The values on columns are combination of double, String, and int.
int myRowCount = aJTableParameter.getRowCount();
int myColumnCount = aJTableParameter.getColumnCount();
Object[][] myRowValues = new Object[myRowCount][myColumnCount];
for (int j = 0; j < myRowCount; j++) {
for(int i = 0; i< myColumnCount; i++){
myRowValues[j][i] = aDestinationTable.getValueAt(j, i);
}
}
System.out.println(Arrays.toString(myRowValues));
if (Arrays.asList(myRowValues).contains(column1Value)
&& Arrays.asList(myRowValues).contains(column2Value)
&& Arrays.asList(myRowValues).contains(column3Value)
&& Arrays.asList(myRowValues).contains(column4Value)) {
JOptionPane.showMessageDialog(null, "Duplicate, try again.");
}else{
//do something else
}
I only get this output:
run:
Successfully recorded login timestamp
[]
[[Ljava.lang.Object;#35fa3ff2]
[[Ljava.lang.Object;#407c448d, [Ljava.lang.Object;#1e78a60e]
Is there any other alternative than using 2 Dimensional Arrays?
I'd appreciate any help.
Thanks.
IFF your JTable cells contain only Strings, you can define your array as String[][] instead of Object[][] and fill it with your JTable contents using aDestinationTable.getValueAt(j, i).toString().
EDIT: since that's not the case (as per your comment), it's probably better to use a List, like this:
List<List<Object>> objectList = new ArrayList<>();
for (int j = 0; j < 2; j++) {
objectList.add(j, new ArrayList<>());
for (int i = 0; i < 2; i++) {
if (i==0) objectList.get(j).add("string" + j + i);
if (i==1) objectList.get(j).add((double) 37.8346 * j * i);
}
}
System.out.println("OBJECT LIST: "+objectList);
Output:
OBJECT LIST: [[string00, 0.0], [string10, 37.8346]]
Your code should look like this, then:
List<List<Object>> myRowValues = new ArrayList<>();
for (int j = 0; j < myRowCount; j++) {
myRowValues.add(j, new ArrayList<>());
for (int i = 0; i < myColumnCount; i++) {
myRowValues.get(j).add(aDestinationTable.getValueAt(j, i));
}
}
System.out.println(myRowValues);
I am attempting to solve a semi-difficult problem in which I am attempting to create an array and return a 3 dimensional array based on the parameter which happens to be a 2 dimensional int array. The array I'm attempting to return is a String array of 3 dimensions. So here is the code:
public class Displaydata {
static String[][][] makeArray(int[][] dimensions) {
String myArray[][][];
for (int i = 0; i < dimensions.length; i++) {
for (int j = 0; j < dimensions[i].length; j++) {
myArray[][][] = new String[i][j][]; //getting error here.
}
}
return myArray;
}
static void printArray(String[][][] a) {
for (int i = 0; i < a.length; i++) {
System.out.println("\nrow_" + i);
for (int j = 0; j < a[i].length; j++) {
System.out.print( "\t");
for (int k = 0; k < a[i][j].length; k++)
System.out.print(a[i][j][k] + " ");
System.out.println();
}
}
}
public static void main(String[] args) {
int [][] dim = new int[5][];
dim[0] = new int[2];
dim[1] = new int[4];
dim[2] = new int[1];
dim[3] = new int[7];
dim[4] = new int[13];
dim[0][0] = 4;
dim[0][1] = 8;
dim[1][0] = 5;
dim[1][1] = 6;
dim[1][2] = 2;
dim[1][3] = 7;
dim[2][0] = 11;
for (int i = 0; i < dim[3].length;i++)
dim[3][i] = 2*i+1;
for (int i = 0; i < dim[4].length;i++)
dim[4][i] = 26- 2*i;
String[][][] threeDee = makeArray(dim);
printArray(threeDee);
}
}
As you can see from the source code, I'm getting an error when I try to create an instance of my 3-dimensional array which I'm attempting to return. I'm supposed to create a three dimensional array with the number of top-level rows determined by the length of dimensions and, for each top-level row i, the number of second-level rows is determined by the length of dimensions[i]. The number of columns in second-level row j of top-level row i is determined by the value of dimensions[i][j]. The value of each array element is the concatenation of its top-level row index with its second-level row index with its column index, where indices are represented by letters : ‘A’ for 0, ‘B’ for 1 etc. (Of course, this will only be true if the indices don’t exceed 25.) I don't necessarily know where I'm going wrong. Thanks!
You should not be initializing the array on every iteration of the loop. Initialize it once outside the loop and then populate it inside the loop.
static String[][][] makeArray(int[][] dimensions) {
String[][][] myArray = new String[25][25][1];
for (int i = 0; i < dimensions.length; i++) {
for (int j = 0; j < dimensions[i].length; j++) {
myArray[i][j][0] = i + "," + j;
}
}
return myArray;
}
I just plugged in values for the size of the first two dimensions, you will need to calculate them based on what you put in there. The 'i' value will always be dimensions.length but the 'j' value will be the largest value returned from dimensions[0].length -> dimensions[n-1].length where 'n' is the number of elements in the second dimension.
Also you will need to set up a way to convert the numbers in 'i' and 'j' to letters, maybe use a Map.
I guess you should initialize the array as
myArray = new String[i][j][]; //getting error here.
I think
myArray[][][] = new String[i][j][]; //getting error here.
should be:
myArray[i][j] = new String[5]; // I have no idea how big you want to go.
And then you can fill in each element of you inner-most array like such:
myArray[i][j][0] = "first item";
myArray[i][j][1] = "second string";
...
I think you should just change that line to:
myArray = new String[i][j][]; //look ma! no compiler error
Also, you would need to initialize myArray to something sensible (perhaps null?)
I got this class :
import java.util.*;
public class MatrixArrayList extends AbstractMatrix {
private ArrayList<ArrayList<Integer>> values;
public MatrixArrayList(int nbl, int nbc) {
super(nbl, nbc);
values=new ArrayList<ArrayList<Integer>>();
}
#Override
public int getValue(int x, int y) {
return values.get(x).get(y) ;
}
#Override
public void setValue(int x, int y, int value) {
values.get(x).set(y, value);
}
}
and I got
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
I want to make a matrix with an ArrayList
i have w problem with this :
valeurs.get(x).set(y, valeur);
It's not clear from your code which call causes the exception, however it is clear that you are not initializing your inner array-list, nor are you adding any objects to it.
When you initialize it in the constructor:
values=new ArrayList<ArrayList<Integer>>();
What you're basically doing is instantiating the values object to be an ArrayList of size 0 (no items have been added to it yet).
Then, if say, you're doing setValue at index 0, you get the exception because when you do get(x), you're basically doing get(0) on a collection of size 0 - there is nothing to get, you exceed the bounds of the your array.
What you might want to do is initialize all arrays in the constructor:
public MatrixArrayList(int nbl, int nbc) {
super(nbl, nbc);
values=new ArrayList<ArrayList<Integer>>(nbl);
for (int i = 0; i < nbl; i++) {
values.add(new ArrayList<Integer>(nbc));
}
}
And then you can access them without a problem in getValue or setValue (you'll get this exception if you actually do exceed the bounds or if you haven't set any value at the specific index yet. See comment below:).
Notice, though, that since you're using the ArrayList object, rather than a primitive int[] array, you still don't have values inside your array. Simply doing new ArrayList<Integer>() or even new ArrayList<Integer>(num) still leaves you with a list of size 0. If you want to cover all your bases, you might want to either initailize your ArrayList, or perform bounds checks before each get you make in either getValue or setValue.
new ArrayList<ArrayList<Integer>>() creates an empty list. To fill that list with values, you need to call add().
Assuming you want to fill matrix with nbl lists of nbc null values:
this.values = new ArrayList<>(nbl);
for (int i = 0; i < nbl; i++) {
ArrayList<Integer> row = new ArrayList<>(nbc);
for (int j = 0; j < nbc; j++)
row.add(null);
this.values.add(row);
}
You could also fill it with 0 values if you want.
Of course, if the matrix cannot change size, it would likely be much better to create a simple array version, instead of the ArrayList version you're trying to create.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Shell {
static List<ArrayList<ArrayList<Double>>> read(String filename) {
ArrayList<ArrayList<Double>> A = new ArrayList<ArrayList<Double>>();
ArrayList<ArrayList<Double>> B = new ArrayList<ArrayList<Double>>();
String thisLine;
try {
BufferedReader br = new BufferedReader(new FileReader(filename));
// Begin reading A
while ((thisLine = br.readLine()) != null) {
if (thisLine.trim().equals("")) {
break;
} else {
ArrayList<Double> line = new ArrayList<Double>();
String[] lineArray = thisLine.split("\t");
for (String number : lineArray) {
line.add((double) Integer.parseInt(number));
}
A.add(line);
}
}
// Begin reading B
while ((thisLine = br.readLine()) != null) {
ArrayList<Double> line = new ArrayList<Double>();
String[] lineArray = thisLine.split("\t");
for (String number : lineArray) {
line.add((double) Integer.parseInt(number));
}
B.add(line);
}
} catch (IOException e) {
System.err.println("Error: " + e);
}
List<ArrayList<ArrayList<Double>>> res = new LinkedList<ArrayList<ArrayList<Double>>>();
res.add(A);
res.add(B);
return res;
}
static int[][] ijkAlgorithm(ArrayList<ArrayList<Integer>> A,
ArrayList<ArrayList<Integer>> B) {
int n = A.size();
// initialise C
int[][] C = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
C[i][j] += A.get(i).get(k) * B.get(k).get(j);
}
}
}
return C;
}
static void printMatrix(Matrix matrix, int n) {
for (int i = 0; i < n; i++) {
StringBuilder sb = new StringBuilder(matrix.length);
for (int j = 0; j < n; j++) {
if (j != 0) {
sb.append("\t");
}
String formattedString = String.format("%.0f", matrix.get(i, j))
sb.append(formattedString);
}
System.out.println(sb.toString());
}
}
public static void main(String[] args) {
String filename;
if (args.length < 2) {
filename = "2000.in";
} else {
filename = args[1];
}
List<ArrayList<ArrayList<Double>>> matrices = read(filename);
ArrayList<ArrayList<Double>> A = matrices.get(0);
ArrayList<ArrayList<Double>> B = matrices.get(1);
int n = A.size();
double[][] Aarray = new double[n][n];
double[][] Barray = new double[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
Aarray[i][j] = A.get(i).get(j);
Barray[i][j] = B.get(i).get(j);
}
}
Matrix AM = new Matrix(Aarray);
Matrix BM = new Matrix(Aarray);
Matrix CM = AM.times(BM);
printMatrix(CM, n);
}
}
input file that have matrices you want to do this operation
Hope this code helps happy coding.
After a thorough survey of this and many other Internet communities I failed to solve my problem. It is about ControlP5 button and my aim of importing 2D array from previously formated text file with two columns and 19 rows and space separated values. Now my code works but the 2D arrray I designated to hold the values from the txt does not get all of the values but just the last pair in its first row. I know that for loops over all values but stores them only in the first row. I dont know how to push it in another row for reading. This is my code:
if(theEvent.isController())
{
if(theEvent.controller().name() == "mean shape males")
{
String loadPath1 = selectInput();
reader = createReader(loadPath1); //new BufferedReader
int x=0; //rows
int y=0; //columns
String smaLine;
try
{
while ((smaLine = reader.readLine()) != null)
{
String[] values = smaLine.split(", ");
for(int i = 0; i < values.length; i++)
{
float[] testC = float(split(values[i], " "));
for (int j = 0; j < testC.length; j++)
{
mat1[j][i] = testC[j]; //THIS IS THE PROBLEMATIC MATRIX
}
}
x = x+1;
}
}
catch (IOException e)
{
e.printStackTrace();
}
mat1max = maxRet(mat1);
mat1min = minRet(mat1);
inputMat = new Grid(2,19,10,130,22,mat1,mat1min,mat1max);
}
}
I used all the advice I could find on Stack Overflow mainly from this post How to print 2D Array from .txt file in Java but I just can`t seem to move the reader onto rows other then the first.
I'm guessing that instead of resetting the elements in mat1 you want to create a new matrix for each line and store them in a list of some kind. This is how you might do it:
List<?> matrices = new ArrayList<?>();
while ((smaLine = reader.readLine()) != null)
{
float[][] mat = new float[MATRIX_ROWS][MATRIX_COLUMNS];
String[] values = smaLine.split(", ");
for(int i = 0; i < values.length; i++)
{
float[] testC = float(split(values[i], " "));
for (int j = 0; j < testC.length; j++)
{
mat[j][i] = testC[j];
}
}
matrices.add(mat);
x = x+1;
}
Where is x used, by the way?
Swap your mat1[j][i] = testC[j] to mat1[i][j] = testC[j]