Get csv and compare lines. ArrayList? Java - java

i dont't use java very often and now i got some Problem.
I want to read a CSV file like this one:
A,B,C,D
A,B,F,K
E,F,S,A
A,B,C,S
A,C,C,S
Java don't know dynamic arrays, so i choose an ArrayList. This works so far. The Problem is:
How can I store the ArrayList? I think an other ArrayList would help.
This is what I got:
BufferedReader reader = new BufferedReader(
new InputStreamReader(this.getClass().getResourceAsStream(
"../data/" + filename + ".csv")));
List rows = new ArrayList();
String line;
while ((line = reader.readLine()) != null) {
rows.add(Arrays.asList(line.split(",")));
}
Now I get an ArrayList with a size of 5 for rows.size().
How do I get row[0][0] for example?
What do I want to do? The Problem is i want to find the same row except the last column.
For example i want to find row 0 and row 3.
thank you very much
Thank you all! You helped me a lot. =) Maybe Java and I will become friends =) THANKS!

You don't need to know the row size in advance, String.split() returns a String array:
List<String[]> rows = new ArrayList<String[]>();
String line = null;
while((line = reader.readLine()) != null)
rows.add(line.split(",", -1));
To access a specific row:
int len = rows.get(0).length;
String val = rows.get(0)[0];
Also, are you always comparing by the entire row except the last column? You could just take off the last value (line.replaceFirst(",.*?$", "")) and compare the rows as strings (have to be careful of whitespace and other formatting, of course).
A slightly different way:
Set<String> rows = new HashSet<String>();
String line = null;
while((line = reader.readLine()) != null){
if(!rows.add(line.substring(0, line.lastIndexOf(','))))
System.out.println("duplicate found: " + line);
}
Of course, modify as necessary if you actually need to capture the matching lines.

You'll need to declare an ArrayList of arrays. Asuming that csv file has a known number of columns, the only dynamic list needed here are the "rows" of your "table", formed by an ArrayList(rows) of arrays char[] (columns). (If not, then an ArrayList of ArrayList is fine).
It's just like a 2D table in any other language: an array of arrays. Just that in this case one of the arrays needs to be dynamic.
To read the file you'll need two loops. One that reads each line, just as you're doing, and another one that reads char per char.
Just a quick note: if you are going to declare an array like this:
char[] row = new char[5];
and then going to add each row to the ArrayList like this:
yourList.add(row);
You will have a list full of pointers to the same array. You'll need to use the .clone() method like this:
yourList.add(row.clone());
To access it like table[1][2], you'll need to use arraylist.get(1).get(2);

Related

Looking for elegant way of searching through an array of strings for duplicate entries. Brute force method works

I have a file of alphanumeric VIN numbers from vehicles (saved as strings). I need to parse through this file and determine
1) Is a VIN duplicated? If so, how many times
2) Write the duplicated VIN and the total number of duplicates to a text file
I have gotten it to work using the brute force method dual nested For loops. Am looking for a more elegant way to parse the strings. I'm using Java 7 in NetBeans 8.2 and it doesn't appear to like using the .set or hashmap.
Constraints
1) The VINs may be in any order
2) The duplicates can be scattered through the file at random
/* a) Open input and output files
*/
try {
inputStream = new BufferedReader(new FileReader(fileName));//csv file
outputStream = new PrintWriter(new FileWriter("DuplicateVINs.txt"));
/* b) Read in file line by line
then slice out the 17 digit VIN from the extra data I don't care about
*/
while ((thisLine = inputStream.readLine()) != null) {
l = thisLine.substring(1, 18);
linesVIN.add(l.split(","));//why does this split have to be here?
}
/*c) Now that the List is full calculate its size and then write to array of strings
*/
String[][] inputArray = new String[linesVIN.size()][];
i=linesVIN.size();
System.out.println(i);
linesVIN.toArray(inputArray);
/* d) Will use two nested For loos to look for duplicates
*/
countj=0;
countk=0;
for (int j = 1;j<=i-1; j++){ //j loop
duplicateVIN=Arrays.toString(inputArray[j]);
for(int k=1;k<=i-1;k++){
if(duplicateVIN.equals(Arrays.toString(inputArray[k]))){
countk=countk+1;
foundFlag=true;
} else{
//
if(countk>=2){
//if(j!=k){
System.out.println(duplicateVIN + countk);
//} // see if removes the first duplicate
}
foundFlag=false;
countk=0;
}
} //ends k loop
countj=j;
} //ends j loop
} //Completes the try
[2q3CDZC90JH1qqqqq], 3
[2q4RC1NG1JR1qqqqq], 4
[2q3CDZC96KH1qqqqq], 2
[1q4PJMDN8KD1qqqqq], 7
I'm using Java 7 in NetBeans 8.2 and it doesn't appear to like using the .set or hashmap.
Your first step should be to figure out what you're doing wrong with a map. A hashmap is the perfect solution for this problem, and is really what you should be using.
Here's a broad example of how the solution would work, using the information you provided.
Map<String,Integer> countMap = new HashMap<String,Integer>();
while ((thisLine = inputStream.readLine()) != null) {
l = thisLine.substring(1, 18);
if(countMap.containsKey(l)){
countMap.put(l, countMap.get(l)+1);
}else{
countMap.put(l,1);
}
}
I'm assuming that the while loop your provided is properly iterating over all VIN numbers.
After this while loop is completed you would just need to output the values of each key, similar to this:
for(String vin : countMap.keySet()){
System.out.println("VIN: "+vin+" COUNT: "+countMap.get(vin));
}
If I've read your problem correctly, there is no need for a nested loop.

Comparison of values from file not working in java

Currently i am stuck up with a issue regarding comparing values in a text file. Below is my requirement which is a bit unique is what i can say.
I am getting a text file which is having data in the below format. The lines are a series of numbers of a particular format.
223---other line values
354---other line value
756---other line values
754---other line values
854---other line values
923---other line values
I have to validate that all the lines are starting in this order 2,3,7,8,9. There can be multiple lines in between 2 & 9 starting with 2,3,7,7,8,3,7,7,8,9. It is guranteed that 2 and 9 lines will be the first and last lines in the file. Multiple 7's can appear between 3 & 8.
I came up with the logic below for this comparison but the logic works for only one combination of lines starting with 2,3,7,7,8,9.
When there are multiple occurrences of lines like say 2,3,7,7,8,3,7,7,8,9 it does not work. Can someone please help me with what is wrong here and how i can solve this issue. If there is a better option or any other better way for my requirement please suggest so that i can use it. The volume in the input file is not high and can be almost 10 to 20 thousand.
Set<String> recordTypeOrder = new HashSet<>();
BufferedReader rdr = new BufferedReader(new StringReader("path to my file here"));
for (String line = rdr.readLine(); line != null; line = rdr.readLine()) {
if(line.startsWith("2")){
recordTypeOrder.add("2");
}else if(line.startsWith("3")){
recordTypeOrder.add("3");
}else if(line.startsWith("7")){
recordTypeOrder.add("7");
}else if(line.startsWith("8")){
recordTypeOrder.add("8");
}else if(line.startsWith("9")){
recordTypeOrder.add("9");
}
}
Set<String> orderToCompare = new TreeSet<>(recordTypeOrder);
boolean compare = orderToCompare.equals(actualOrder());
if(!compare){
logger.info("== Processing failed =====");
throw new CustomException("======= Processing failed =======");
}
private static Set<String> actualOrder(){
Set<String> actualOrder= new HashSet<>();
actualOrder.add("2");
actualOrder.add("3");
actualOrder.add("7");
actualOrder.add("8");
actualOrder.add("9");
return actualOrder;
}
Many Thanks
You need to store both order and count of 3,7,7,8. I think treeset won't work. Can you try others data structures like LinkedHashMap. That way you could just store the data you need in LinkedHashMap and then write a custom function to validate it.

Setting two different text files as seperate string arrays and finding matches from the two arrays in Java

So basically i'm trying to take two text files (one with many jumbled words and one with many dictionary words.) I am supposed to take these two text files and convert them to two seperate arrays.
Following that, I need to compare jumbled strings from the first array and match the dictionary word in the second array up to it's jumbled counterpart. (ex. aannab(in the first array) to banana(in the second array))
I know how to set one array from a string, however I don't know how to do two from two seperate text files.
Use HashMap for matching. Where first text file data will be the key of Map and second text file data will be value. Then, by using key, you will get matching value.
you can read each file into an array like this:
String[] readFile(String filename) throws IOException {
List<String> stringList = new ArrayList<>();
try {
FileInputStream fis = new FileInputStream(new File(filename));
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String line = null;
while ((line = br.readLine()) != null) {
stringList.add(line);
}
} finally {
br.close();
}
return stringList.toArray(new String[stringList.size()]);
}
Next, try to do the matching:
String[] jumbles = readFile("jumbles.txt");
String[] dict = readfile("dict.txt);
for (String jumble : jumbles) {
for (String word : dict) {
// can only be a match if the same length
if (jumble.length() == word.length()) {
//next loop through each letter of jumble and see if it
//appears in word.
}
}
}
I know how to set one array from a string, however I don't know how to do two from two seperate text files
I would encourage you to divide your problems don't knows and knows.
Search don't knows over internet you will get lot of ways to do it.
Then search for what you know,to explore whether it can be done in a better way.
To help you here,
Your Don't knows:
Reading file in Java.
Processing the content of read file.
Your known part :
String to array representation ( Search whether there are better ways in your use case)
Combine both :-)

Appending text from array list to a String takes a lot of time

I am reading a Simple Notepad Text file containing a lot of data actually in a 3mb of size so you can imagine the number of words it can have! The problem is I am reading this file into a string then splits the string so that I can hold each single word inside an ArrayList(String). It works fine for me but the actual problem is that I am processing this array list for some purpose and then again I have to append or you can say put all the words of array list back to the String!
so that the steps are:
I read a text file into a String (alltext)
Split all words into an arraylist
process that array list (suppose I removed all the stop words like is, am, are)
after processing on array list I want to put all the words of array list back to the string (alltext)
then I have to work with that string (alltext)
(alltext is the string that must contains the text after all processing)
The problem is that at step number 4 it takes a lot of time to append all the words back to the string my code is:
BufferedReader br = new BufferedReader(new FileReader(file));
String line = "";
while ((line = br.readLine()) != null) {
alltext += line.trim().replaceAll("\\s+", " ") + " ";
}
br.close();
//Adding All elements from all text to temp list
ArrayList<String> tempList = new ArrayList<String>();
String[] array = alltext.split(" ");
for (String a : array) {
tempList.add(a);
}
//remove stop words here from the temp list
//Adding File Words from List in One String
alltext = "";
for (String removed1 : tempList) {
System.out.println("appending the text");
alltext += removed1.toLowerCase() + " ";
//here it is taking a lot of time suppose 5-10 minutes for a simple text file of even 1.4mb
}
So I just want any idea so that I can reduce the time for an efficient processing and relax the machine! I will be thankful for any suggestions and ideas...
Thanks
Use a StringBuffer instead of a String.
A String is immutable and thus you create a new Object everytime you append, which takes more and more time the longer your String becomes. A StringBuffer is mutable and made for cases like yours.
I would recommend StringBuilder
According to this stringbuilder-and-stringbuffer-in-java it's faster than a StringBuffer also check if you need the ArrayList because you can iterate through the array too

Android - how to delete last 2 lines from String?

I have a String which always looks like this:
data
data
data
data
non-data
non-data
And I need to delete the 2 last lines from it. The lenght of these lines can be different. How I can do that fast (String = ~1000 lines)?
I'd say something along the lines of:
String[] lines = input.split("\n");
String[] dataLines = Arrays.copyOfRange(lines, 0, lines.length - 2);
int lastNewLineAt = string.lastIndexOf("\n");
string.subString(0, string.lastIndexOf("\n", lastNewLineAt));
You can use constant for new line character reading system property
This Code will split your text by "\n" 's which means your lines in to a String Array.
Than you will get that array's length..
And in a for loop you will set and append your text till your length-1 element.
This may be a long approach but I was searching this and I couldn't find anything.
This was my easiest way.
String[] lines = YourTextViev.getText().toString().split("\n");
YourTextView.setText(""); // clear your TextView
int Arraylength = lines.length-1; // Changing "-1" will change which lines will be deleted
for(int i=0;i<Arraylength;i++){
YourTextView.append(lines[i]+"\n");
}

Categories