Finding the Length of a String within an ArrayList - java

I am writing a CSVParser program that seperates words at commas. I am currently trying to find and record the longest word that appears in the file. Here is my class.
import csv.CSVParser;
import java.io.*;
import java.util.*;
public class RecordFormatter {
public static void main (String[] args) {
CSVParser parser = new CSVParser(new File (args[0]));
while (parser.hasNextLine()) {
ArrayList<String> ls = parser.getNextLine();
for (int i = 0; i<ls.size(); i++) {
System.out.print("|" + ls.get(i) + " ");
}
System.out.print("|");
System.out.println();
}
CSVParser parser1 = new CSVParser(new File (args[0]));
ArrayList<Integer> maxCol = new ArrayList<Integer>();
while (parser1.hasNextLine()) {
ArrayList<String> ls1 = parser1.getNextLine();
for (int i = 0; i<ls1.size(); i++) {
maxCol.add(ls1.get(i)); //Here is where my bug occurs.
}
}
}
}
I have created two CSVParsers and am trying to use the second of the two to record the length. I tried (as you can see above) storing the int length value of each word into another Arraylist, but I can't seem to get it to work. Any help would be much appreciated.

Without giving the solution, since this is homework...
Notice that you are keeping every length value rather than comparing the current length against a previous value to determine if it is longer and only then keeping it.
Seems like you need just a single maxLength Integer (or int) rather than a list since you just want the longest single word.
If you wanted the longest word per line, a List might then be appropriate.
Another option would be to use a SortedList and get the largest value (last value) in the list.

Related

Scan array of doubles in a file | Java

I was trying to scan a file that has an array of doubles. I'm using the code below but it's only outputting 0.0 for every entry. Why is this and how can I fix it?
Scanner scanner = new Scanner("file.txt");
double[] array = new double[256 * 256];
for (int i = 0; i < array.length; i++) {
if (scanner.hasNextDouble()) {
array[i] = scanner.nextDouble();
}
}
System.out.println(array[0]);
An example of the file I'm scanning is
0.22131145 0.22131145 0.22131145 0.22841525 0.22841525 ...
The main issue is with the instantiation of the Scanner object. In this case you need to pass a File object into it, not just a string, and make sure you specify the correct file path. Refer to the official documentation for advice.
Secondly, you need to use a while-loop. An if-statement will execute only once, but you would want the Scanner to continue looking whilst there is info inside the file.
Thirdly, don't use an array for storing the values. It's too risky because you need to know the size of the array beforehand, meaning that you would need to loop twice, which would be inefficient, or you are hard coding, as you are doing here. If someone were to add or remove values from the file, you will get unexpected results. Rather use a dynamic data structure such as a List.
public static void main(String[] args) throws FileNotFoundException {
String filepath = "file.txt";
Scanner scanner = new Scanner(new File(filepath));
List<Double> list = new ArrayList<>();
while (scanner.hasNextDouble()) {
list.add(Double.valueOf(scanner.next()));
}
scanner.close();
System.out.println(list.get(0));
}
There are four problems with your code:
Blocker: Scanner expects a File object but you haven't used it in this way. You need to use the following syntax:
Scanner scanner = new Scanner(new File("file.txt"));
Performance: You can improve the performance of your program by including scanner.hasNextDouble() in the condition which checks the value of i, as shown below:
for (int i = 0; i < array.length && scanner.hasNextDouble(); i++) {
array[i] = scanner.nextDouble();
}
This will terminate the loop as soon as scanner.hasNextDouble() returns false; otherwise, the loop in your code will continue to run until i < array.length evaluates to false irrespective of the value returned by scanner.hasNextDouble().
Resource leak: You have not closed the Scanner object. Put the following line after the loop finishes:
scanner.close();
Missed functionality: You haven't printed the complete array. Your statement, System.out.println(array[0]) will print only the first element in the array. Change it as follows to print the complete array:
System.out.println(Arrays.toString(array));
Given below the code incorporating all the above-mentioned comments:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("file.txt"));
double[] array = new double[256 * 256];
for (int i = 0; i < array.length && scanner.hasNextDouble(); i++) {
array[i] = scanner.nextDouble();
}
scanner.close();
System.out.println(Arrays.toString(array));
}
}
Memory utilization: You have used a fixed-sized array which is fine if the number of elements to be stored is equal to the size of the array. However, if it is not the case (i.e. if the number of elements to be stored can be less than or more than the specified size), you should use a Collection e.g. an ArrayList which is a kind of dynamic array. This will help you in many ways: (a) You will save memory if the number of elements to be stored is less than the specified size (b) You do not need to change your code in order to increase the size of the array when you need to store more elements than you have already specified (c) The Collection provides with a rich API to deal with elements. By leveraging this API, your code can be crisp, more performant, maitainable etc.
Given below the code incorporating the 5th point:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("file.txt"));
List<Double> list = new ArrayList<>();
while (scanner.hasNextDouble()) {
list.add(scanner.nextDouble());
}
scanner.close();
System.out.println(list);
}
}

Assigning multiple strings to single variable

So i'm working on a bowling calculator assignment that takes a series of inputs and calculates a score. The test input provided by my instructor has a number of test cases which denote how many strings will need to be computed to scores. The problem I am having is that I am not able to get all 3 strings (there are 3 test cases) into a single string, separated on different lines.
This is what the input is:
3
--,--,--,--,--,--,--,--,--,--
X,X,X,X,X,X,X,X,X,XXX
X,13,X,81,5/,X,18,33,X,X36
I am trying to get it to be formatted as such:
--,--,--,--,--,--,--,--,--,--
X,X,X,X,X,X,X,X,X,XXX
X,13,X,81,5/,X,18,33,X,X36
However, when I run my code I get this as the output:
--,--,--,--,--,--,--,--,--,--
X,X,X,X,X,X,X,X,X,XXX
X,13,X,81,5/,X,18,33,X,X36
Here is what I've got so far.
import java.io.*;
import java.util.*;
public class Bowling {
public static void main(String[] args) throws FileNotFoundException {
File inFile = new File("input.txt");
Scanner scanFile = new Scanner(inFile);
int tc = scanFile.nextInt();
String N = "";
for (int i=0; i < tc; i++)
N += scanFile.next();
System.out.println(N);
}
}
**UPDATE: Thank you everyone for the answers, I have learned quite a bit because of your responses. At the time of asking this question I was tied up on this problem and was not thinking straight. I looked over my code again and realized all i had to do was add this line before the strings were added to the variable:
N += "\n";
Again, thanks to all those who commented.
I recommend using a StringBuilder if you are going to be concating a lot of String's. But on every iteration of the loop, you can append a newline character:
StringBuilder sb = new StringBuilder();
for (int i=0; i < tc; i++) {
sb.append(scanFile.next());
sb.append("\n");
}
System.out.println(sb);
It is possible to:
• Make a String[] array
• Use dividers, like \t
• Use other methods
Also, don't forget to say that you want us to tell you how to use newline characters.
I'd love to use StringJoiner in your case,I totally agree with #GBlodgett's answer. But this too can serve as an alternate.
From the javadoc,
StringJoiner is used to construct a sequence of characters separated
by a delimiter
which exactly suits your case. Your loop reads as,
StringJoiner sj= new StringJoiner("\n"); // Here, "\n" is the delimiter between every join.
for (int i=0; i < tc; i++){
sj.add(scanFile.next());
}
System.out.println(sj.toString());
Also, this avoids appending unnecessary newline after the last appended line.
I've found a bug in your code that explains why the output is in one line.
The command System.out.println(N) should be inside the for loop.
The variable N is unnecessary - please omit it.
There is another problem of resource leakage in your code, because the Scanner was never closed. The scanner should be closed using the auto closeable mechanism (by using try with resource statement).
I propose the following code to solve the problem:
public static void main(String[] args) throws FileNotFoundException {
File inFile = new File("input.txt");
try (Scanner sc = new Scanner(inFile)){
int tc = sc.nextInt();
for (int i=0; i < tc; i++) {
System.out.println(sc.next());
}
}
}

Getting Objects From A Text File

I have a text file like this;
7-Georgia
1-Andrew
6-John
8-Luke
9-Erica
3-Kim
2-Jude
5-Phil
4-Leo
The first column is id and second is name. How can I get these id's and names? So far I wrote this;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class Main {
#SuppressWarnings("resource")
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
#SuppressWarnings("unused")
Scanner fromFile = new Scanner(new File("id_name.txt"));
fromFile.useDelimiter("-");
while(fromFile.hasNext()){
String temp = fromFile.next();
System.out.println(temp);
}
while(fromFile.hasNext()){
String temp= fromFile.next();
int[] fileID;
fileID= new int[9];
for(int i=0; i<9; i++){
fileID[i]= Integer.parseInt(temp);
}
System.out.println(fileID);
}
}
}
But this doesn't get the id's. I'm not sure how to fix this, I'd be grateful if you help me.
You have two while loops in your code. Typically one while loop will go through every item until the condition is no longer true. I think you need to rework this to have a better "flow of control" which might mean using only one while loop (with sections to grab the number and then the name.
I imagine that you are looking for results from the second while loop, but by the time you get to it, the first while loop will have exhausted all of your data.
Finally, printing an array will print out the array reference identifier. If you want to actually print the contents of the array, you need a loop over the elements within the array, and you need to print out each array element explicitly.
As an alternative to the array printing technique above (which you should master), you can also use the Arrays.toString(<insert array here>) method call. However, in many cases it will give you a format that is not desired. That's why you need to know the above technique too.
Also, you have one hidden issue. You (in the second while loop) make the assumption that there are only nine inputs. Pay close attention to what you are writing. Every time you have to reach for a number, consider whether it is a "magic" number. Magic numbers are numbers that are in your code with no explanation or reason why they exist. They are indicators of errors in the code made by assumptions that probably won't last the test of time.
For example, you are using the number 9 because you have seen the input file. The next input file will probably not have nine entries in it, and your program will probably not work right if you gave it an input with eight entries, or an input with ten entries. Perhaps you should rewrite the loop to remove the magic number, by making the logic process while there is still (some) input.
Try this on for size
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try {
Scanner fromFile = new Scanner(new File("id_name.txt"));
} catch (FileNotFoundException e) {
System.err.println("File not found");
}
String[] arr = new String[9];
String[] oth = new String[9];
int i = 0;
while(fromFile.hasNextLine()) {
String temp = fromFile.nextLine();
oth[i] = temp.substring(0,1);
arr[i] = temp.substring(2);
i++;
}
int[] fileID;
fileID = new int[9];
for(int j = 0; j < 9; j++) {
fileID[j] = Integer.parseInt(oth[j]);
}
}
}
this should go through and retrieve the numbers(.substring(0,1)) and then the names(.substring(2)), and then converting the numbers to int values.
Try the following:
File file=new File("id_name.txt");
int[] fileID;
fileID= new int[9];
String[] result = file.nextLine().split("-");
for (int x = 0; x < result.length; x++){
if (Character.isDigit(result[x])) { // use the isDigit method to get the ids
System.out.println("this is an id");
fileID[i]= Integer.parseInt(result[x]);
}
Actually my friend, there are several mistakes here.
1) When the first while loop completes, it leaves fromfile.hasNext() as false Hence the second loop never starts.
>> To fix this, You need to put it all in one while loop.
2) fileID is an array. You cannot print it using System.out.println(fileID).
>> You have to tell what kind of output you want. The code will depend on that. For simply printing all the values, you need to make a for loop that prints each value separartely. You should use fileID.length for the no. of times you need to loop it.
3) Basically, fromfile.next() is not the way to do it.
>> You need to use fromfile.nextLine().

find common words in multiple text files

I have 100 text files. 50 of them are called text_H and the other are called text_T. What I would like to do is the following open two text files text_T_1 and text_H_1 and find the number of common words and write it to a text file then open text_H_2 and text_T_2 and find the number of common words....then open text_H_50 and text_T_50 and find the number of common words.
I have written the following code that open two text files and find common words and return the the number of common words between the the two files. The results are written in text file
For whatever reason instead of giving me the number of common word for just the open text files, it gave me the number of of common words for all files. For the example if the number of common words between fileA_1 and fileB_1 is 10 and the number of common words between fileA_2 and fileB_2 is 5, then result I get for number of common word for the second two files is 10+5=15.
I'm hoping someone here can catch whatever it is that I'm missing, because I've been through this code many times now without success. Thanks ahead of time for any help!
The code:
package xml_test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class app {
private static ArrayList<String> load(String f1) throws FileNotFoundException
{
Scanner reader = new Scanner(new File(f1));
ArrayList<String> out = new ArrayList<String>();
while (reader.hasNext())
{
String temp = reader.nextLine();
String[] sts = temp.split(" ");
for (int i = 0;i<sts.length;i++)
{
if(sts[i] != "" && sts[i] != " " && sts[i] != "\n")
out.add(sts[i]);
}
}
return out;
}
private static void write(ArrayList<String> out, String fname) throws IOException
{
FileWriter writer = new FileWriter(new File(fname));
//int count=0;
int temp1=0;
for (int ss= 1;ss<=3;ss++)
{
int count=0;
for (int i = 0;i<out.size();i++)
{
//writer.write(out.get(i) + "\n");
//writer.write(new Integer(count).toString());
count++;
}
writer.write("count ="+new Integer(temp1).toString()+"\n");
}
writer.close();
}
public static void main(String[] args) throws IOException
{
ArrayList<String> file1;
ArrayList<String> file2;
ArrayList<String> out = new ArrayList<String>();
//add for loop to loop through all T's and H's
for(int kk = 1;kk<=3;kk++)
{
int count=0;
file1 = load("Training_H_"+kk+".txt");
file2 = load("Training_T_"+kk+".txt");
//int count=1;
for(int i = 0;i<file1.size();i++)
{
String word1 = file1.get(i);
count=0;
//System.out.println(word1);
for (int z = 0; z <file2.size(); z++)
{
//if (file1.get(i).equalsIgnoreCase(file2.get(i)))
if (word1.equalsIgnoreCase(file2.get(z)))
{
boolean already = false;
for (int q = 0;q<out.size();q++)
{
if (out.get(q).equalsIgnoreCase(file1.get(i)))
{
count++;
//System.out.println("count is "+count);
already = true;
}
}
if (already==false)
{
out.add(file1.get(i));
}
}
}
//write(out,"output_"+kk+".txt");
}
//count=new Integer(count).toString();
//write(out,"output_"+kk+".txt");
//write(new Integer(count).toString(),"output_2.txt");
//System.out.println("count is "+count);
}//
}
}
Let me show you what your code is doing and see if you can spot the problem.
List wordsInFile1 = getWordsFromFile();
List wordsInFile2 = getWordsFromFile();
List foundWords = empty;
//Does below for each compared file
for each word in file 1
set count to 0
compare to each word in file 2
if the word matches see if it's also in foundWords
if it is in foundWords, add 1 to count
otherwise, add the word to foundWords
//Write the number of words
prints out the number of words in foundWords
Hint: The issue is with foundWords and where you are adding to count. arunmoezhi's comment is on the right track, as well as board_reader's point #3 in his answer.
As it stands now, your code is doing nothing meaningful with any of the count variables
use more meaningful variable names in loops, makes code readable.
use HashMap-s instead of ArrayList-s, will make code smaller, faster and a lot easier. will use less memory too in case words are repeated several times in files.
should not you increase count in already==false case?
could not figure out point of calculating count 3 times in write method, is not count equal to out.size()?
probably there are more too...

Cannot assign a substring from a file to my array

I have a file with 50 states and capitals in this format:
Alabama,Tallahasee,
Wisconsin,Madison,
........
I am trying to assign the states and capitals to seperate arrays and I am having a problem with the for loop. My code is as follows:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class StatesAndCapitals {
public static void main(String[] args) throws FileNotFoundException {
FileInputStream is = new FileInputStream("capitals.txt");
Scanner input = new Scanner(is);
String[] states = new String[50];
String[] capitals = new String[50];
for (int i = 0; i < states.length; i++){
int a = states[i].lastIndexOf(",");
String states1 = states[i].substring(0, a);
states[i] = states1;
input.nextLine();
}//end for loop
System.out.println(states);
}
}
The error I am getting is
Exception in thread "main" java.lang.NullPointerException
at StatesAndCapitals.main(StatesAndCapitals.java:12)
any help would be appreciated.
When you do
states[i].lastIndexOf(",");
you're analyzing the content of states[i]. But that is your destination array, and not the source containing the text. The source is what is returned from input.nextLine(), which should be the first thing you should do at each iteration:
for (int i = 0; i < states.length; i++){
String currentLine = input.nextLine();
// now extract the data from current line, and store them in the arrays.
}
for (int i = 0; i < states.length; i++){
int a = states[i].lastIndexOf(",");
String states1 = states[i].substring(0, a);
states[i] = states1;
input.nextLine();
}//end for loop
This whole loop is backwards. When you first enter at i = 0 you attempt to take a substring of your states array which has never seen any sort of assignment. You then work on that substring within the loop before ending with input.nextLine(); which is never actually used.
The input variable, when used correctly will actually hold data from the file you open and will allow you to manipulate strings with substring. You need to reorder and fix your loop.
The default value for an object is null.
String[] states = new String[50]; //<-- you declare an array that can holds 50 Strings but they're actually null if you don't initialize them.
So when doing states[i].lastIndexOf(","); it throws a NPE.
Same behavior for your capitals array.
Read the Default Values section.
You need to store the datas in a String variable first :
for (int i = 0; i < states.length; i++){
String data = input.nextLine();
// Now process with data and add corresponding parts to states and capitals array
}//end for loop
And then process on this String and add it to the corresponding array.
Not that if you don't have enough lines in your file (less than 50), it will throw java.util.NoSuchElementException because no more lines are found.
You can add this condition to the loop : for (int i = 0; i < states.length && input.hasNextLine(); i++){
When you will get this working correctly, I suggest you to deal with a List.

Categories