I'm trying to create a 2D array from a .txt file, where the .txt file looks something like this:
xxxx
xxxx
xxxx
xxxx
or something like this:
xxx
xxx
xxx
So I need to handle multiple sizes of a 2D array (Note: Each 2D array will not always be equal x and y dimensions). Is there anyway to initialize the array, or get the number of characters/letters/numbers per line and number of columns? I do not want to use a general statement, something like:
String[][] myArray = new Array[100][100];
And then would filling the array using filewriter and scanner classes look like this?
File f = new File(filename);
Scanner input = new Scanner(f);
for(int i = 0; i < myArray[0][].length; i++){
for(int j = 0; j < myArray[][0].length, j++){
myArray[i][j] = input.nextLine();
}
}
You have several choices as I see it:
Iterate through the file twice, the first time getting the array parameters, or
Iterate through it once, but fill up a List<List<SomeType>> possibly instantiating your Lists as ArrayLists. The latter will give you much greater flexibility in the short and long run.
(per MadProgrammer) The third option is to re-structure the file to provide the meta data required to make decisions about the size of the array.
For example, using your code,
File f = new File(filename);
Scanner input = new Scanner(f);
List<List<String>> nestedLists = new ArrayList<>();
while (input.hasNextLine()) {
String line = input.nextLine();
List<String> innerList = new ArrayList<>();
Scanner innerScanner = new Scanner(line);
while (innerScanner.hasNext()) {
innerList.add(innerScanner.next());
}
nestedLists.add(innerList);
innerScanner.close();
}
input.close();
Java Matrix can have each line (which is an array) by your size desicion.
You can use: ArrayUtils.add(char[] array, char element) //static method
But before that, you need to check what it the file lines length
Either this, you can also use ArrayList> as a collection which is holding your data
Related
String path1, path2;
int count = 0, i = 0;
path1 = args[0];
File file = new File(path1);
FileReader reader = new FileReader(file);
Scanner inputFile = new Scanner(reader);
while(inputFile.hasNextInt()) {
inputFile.nextLine();
count++;
}
int[] array1 = new int[count];
while(inputFile.hasNextInt()) {
//inputFile.nextLine();
array1[i] = inputFile.nextInt();
i++;
}
I never had this issue before, but when I try to write values to an array from a text file containing only int values, one per line, my array only returns all "0"s. instead of the numbers in the text file. I'm not sure if it has to do with me using the command line, but it has the correct argument (file destination) entered in my IDE.
Thanks in advance!
Notice that the exit condition of both while loops are the same. If the first ends then the second one will be jumped over as the condition is immediately false. The pointer of the scanner is already at the end of the file (all numbers have been read by the first loop) so there is nothing left to read.
You have 2 options to fix this issue.
Use an ArrayList: Use an ArrayList<int> object to save the numbers in the first loop. The list grows as numbers are entered so you don't need to know the number of lines before making this object, as opposed to needing to know this to make an array.
Scan the file again: In between the loops close the previous filereader and scanner and create a new one. This new scanner will point to the start of the file again and the second loop will run smoothly.
I am trying to take the standard input and create a 2-d grid with it.
The input will be:
n //number of rows and columns
aaaab
bbbba
aaaab
bbbaa
And I want to create a 2-d char array with those characters. I am drawing a blank on the most efficient way to do this. I know it can be done with a few different for loops, but I'm curious of a better way.
Here is what I have so far, just the beginning
Scanner in = new Scanner (System.in);
int n = Integer.parseInt(in.nextLine());
char[][] grid = new char[n][n];
Just have them input a string.
string.toCharArray() and add that to a list...
char[][] d2char = new char[n][n];
for(int i = 0; i < n; i++) {
string s = scanner.read();
d2char[i] = s.toCharArray();
}
or if you have the strings somewhere else do the same thing just add the string as a character array to the char 2d array.
First of all, as Ya Wang suggests, read whole strings and convert them to char array. Second, way more important, use a buffered reader:
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(r.readLine());
char[][] grid = new char[n][];
for(int i = 0; i < n; ++i)
grid[i] = r.readLine().toCharArray();
Building a java.util.Scanner on System.in is easier to remember, but inefficient... Of course if you are manually inserting the grid line by line it will make no difference (as it will make no difference reading a whole line rather than a char at a time) but if you try to pipe a huge grid from a file and make some benchmarking you will notice the difference...
So i'm trying to read some user input which is then checked against two arrays of strings, then if the user input equals something in either of the arrays i want to put the user input into a new array, but when i go to print the new array which should contain the user input it prints that every value in the array is null
String[] VegiFruit = {"Apples", "Lettuce", "Broccoli"};
String[] Meats = {"Ground beef", "Hambuger"};
String[] Input = new String[20];
String[] InputGreen = new String[20];
String done = "done";
Scanner USER_IN = new Scanner(System.in);
Methods Use = new Methods(); //This is another class I have that just makes printing blank lines and borders look nicer
Use.border();
System.out.println("Enter Item name then follow instructions.");
Use.space();
for(int i = 0; i < 21; i++)
{
System.out.print(i+": ");
Input[i] = USER_IN.nextLine();
if(Arrays.asList(VegiFruit).contains(Input))
{
InputGreen[i] = Input[i];
System.out.println(InputGreen[i]); //Prints null for every value
}
}
So am I doing something wrong with the logic? or is it something else?
if(Arrays.asList(VegiFruit).contains(Input))
This line is totally wrong because you are comparing the object(Here Input is an parameter value of .contains method, it is an object) with a List of element, here element of the list is a String value.
So change the code like below,
if (Arrays.asList(VegiFruit).contains(Input[i])) {
InputGreen[i] = Input[i];
System.out.println(InputGreen[i]); //Now it is print the corresponding value.
}
I have two different programs, one which contains a method "addGrade" designed to add a new grade to a 2D array (gradeTable). One array of the 2D array is the category each grade should be in, and the second element is the grades for each category. Here is that program:
public class GradeBook {
private String name;
private char[] categoryCodes;
private String[] categories;
private double[] categoryWeights;
private double[][] gradeTable;
public GradeBook(String nameIn, char[] categoryCodesIn,
String[] categoriesIn, double[] categoryWeightsIn) {
name = nameIn;
categoryCodes = categoryCodesIn;
categories = categoriesIn;
categoryWeights = categoryWeightsIn;
gradeTable = new double[5][0];
}
public boolean addGrade(String newGradeIn) {
char row = newGradeIn.charAt(0);
int grade = Integer.parseInt(newGradeIn.substring(1));
double[] oldArr = gradeTable[row];
double[] newArr = Arrays.copyOf(oldArr, oldArr.length + 1);
newArr[newArr.length - 1] = grade;
gradeTable[row] = newArr;
return row != 0;
}
The second program reads in a file as a command argument. The bolded text represents the grades being read in. The letter stands for that category each grade should be in, and the number is the actual grade. The file is
Student1
5
a Activities 0.05
q Quizzes 0.10
p Projects 0.25
e Exams 0.30
f Final 0.30
**a100 a95 a100 a100 a100
q90 q80 q100 q80 q80 r90
p100 p95 p100 p85 p100
e77.5 e88
f92**
In the second program, I'm trying to loop through each grade in the file and call the addGrade method on it so it will be added to the 2D array. I'm unsure of how to call the method for each individual grade. Also, I'm pretty sure my addGrade method isn't right. Any help would be appreciated. This is the second program:
public class GradeBookApp {
String fileName = "";
String name = "";
char[] categoryCodes = new char[5];
String[] categories = new String[5];
double[] categoryWeights = new double[5];
double[][] gradeTable;
if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
System.out.println("Reading file \"" + args[i] + "\"."
+ "\n\tCreating GradeBook object."
+ "\n\tAdding grades to GradeBook object."
+ "\nProcessing of file complete.");
fileName = args[i];
Scanner scanFile = new Scanner(new File(fileName));
name = scanFile.nextLine();
int catCodes = Integer.parseInt(scanFile.nextLine());
for (i = 0; i < catCodes; i++) {
String[] all = scanFile.nextLine().split(" ");
if(all.length == 3 && all[0].length() == 1 && all[2].matches("(\\d+\\.\\d+)")){
categoryCodes[i] = all[0].charAt(0);
categories[i] = all[1];
categoryWeights[i] = Double.parseDouble(all[2]);
}
}
GradeBook myGB = new GradeBook (name, categoryCodes,
categories, categoryWeights);
You'd be better off with having each list of grades as an ArrayList<Double> rather than a double[]. It's very hard work on the JVM (and on the programmer!) having to copy the whole array each time so that you can increase its length and add a new one. If you use an ArrayList<Double> gradeList, then you can just
gradeList.add(grade);
without needing to do all the copying.
I would also consider having the larger structure as a Map rather than an array. So rather than having a two-dimensional array, you could have a HashMap<Character,List<Double>> that maps the row onto the list of grades for that row. That avoids having to convert between characters and doubles, which you're currently (implicitly) doing.
Finally, the addGrade() method ought to take a char and a double (a row and a new grade), rather than a String: you're making a lot of work for yourself with having to process inappropriate data structures.
Once you've done this, calling addGrade for each item should be fairly easy. Once you've extracted a String representing a particular grade (say, String gr = "e77.5") then you can add to the list inside your HashMap gradeMap like this:
char row = gr.charAt(0);
double grade = Double.parseDouble(gr.substring(1));
gradeMap.get(row).add(grade);
I think you'll need to supply more info if you need more help than that.
You stated that you need to read from a file, but none of your code is actually reading from a file. This should be your first step. Try looking at BufferedReader documentation as well as numerous posts on this site regarding proper methods to perform file IO operations.
I'm assuming your storing your grades in the 2D gradeTable array like: {Category, grade}. You will need to read each row in your file(BufferedReader has methods for this), parse the string (Look at the String documentation, specifically split or substring/indexOf methods) into category and grade, and then populate your array.
Look into using more dynamic data structures, such as ArrayList. This will allow you to expand the size as you add more grades, as well as not having to copy your array into a new array every time the size expands.
I have a .txt file that lists integers in groups like so:
20,15,10,1,2
7,8,9,22,23
11,12,13,9,14
and I want to read in one of those groups randomly and store the integers of that group into an array. How would I go about doing this? Every group has one line of five integers seperated by commas. The only way I could think of doing this is by incrementing a variable in a while loop that would give me the number of lines and then somehow read from one of those lines that is chosen randomly, but I'm not sure how it would read from only one of those lines randomly. Here's the code that I could come up with to sort of explain what I'm thinking:
int line = 0;
Scanner filescan = new Scanner (new File("Coords.txt"));
while (filescan.hasNextLine())
{
line++;
}
Random r = new Random(line);
Now what do I do to make it scan line r and place all of the integers read on line r into a 1-d array?
There is an old answer in StackOverflow about choosing a line randomly. By using the choose() method you can randomly get any line. I take no credit of the answer. If you like my answer upvote the original answer.
String[] numberLine = choose(new File("Coords.txt")).split(",");
int[] numbers = new int[5];
for(int i = 0; i < 5; i++)
numbers[i] = Integer.parseInt(numberLine[i]);
I'm assuming you know how to parse the line and get the integers out (Integer.parseInt, perhaps with a regular expression). If you're sing a scanner, you can specify that in your constructor.
Keep the contents of each line, and use that:
int line = 0;
Scanner filescan = new Scanner (new File("Coords.txt"));
List<String> content = new ArrayList<String>(); // new
while (filescan.hasNextLine())
{
content.add(filescan.next()); // new
line++;
}
Random r = new Random(line);
String numbers = content.get(r.nextInt(content.size()); // new
// Get numbers out of "numbers"
Read lines one by one from the file, store them in a list and generate a random number from the list's size and use it to get the random line.
public static void main(String[] args) throws Exception {
List<String> aList = new ArrayList<String>();
Scanner filescan = new Scanner(new File("Coords.txt"));
while (filescan.hasNextLine()) {
String nxtLn = filescan.nextLine();
//there can be empty lines in your file, ignore them
if (!nxtLn.isEmpty()) {
//add lines to the list
aList.add(nxtLn);
}
}
System.out.println();
Random r = new Random();
int randomIndex=r.nextInt(aList.size());
//get the random line
String line=aList.get(randomIndex);
//make 1 d array
//...
}