Get separate record for each value - java

I have a list, List<String> myList=new ArrayList<String>(); This list contains the list of countries that I am dealing with.
I am dealing with several records. I need to calculate in such a way that a separate entry for records as per country is sorted.I am using the following logic
for(int zTmp = 0; zTmp<myList.size(); zTmp++)
{
System.out.println("COUNTRY IS"+myList.get(zTmp));
if((record).contains(myList.get(zTmp)))
{
// my next step
}
}
How ever I find that each and every record is entering after the if condition. The records are alphabetically sorted as per countries, and records of every country are together. Please correct me.
This is my String
RECORD 1#India$
RECORD 2#India$
RECORD 3#United Arab Emirates$
RECORD 4#United Arab Emirates$
RECORD 5#United Kingdom$
Sorted as per country name.
I need to give a condition such that it enters in the loop for every country ie say RECORD 1,RECORD 2 calculation must be done break; record 3 ,4 break; record 5 like this.
Hope I am more clear now.

Maybe you mean this?
String currentCountry = "";
for (String record : myList) {
// Regex for entire string "^....$"
// Country between '#' and '$' (the latter escaped)
String country = record.replaceFirst("^.*#(.*)\\$$", "$1");
if (!country.equals(currentCountry)) {
currentCountry = country;
... // Deal with next country
}
}

for(int zTmp = 0; zTmp<myList.size(); zTmp++)
{
System.out.println("COUNTRY IS"+myList.get(zTmp));
if((record).contains(myList.get(zTmp)))
{
// my next step
}
}
Your if condition will result in false only if record doesn't contain a country which is not present in complete myList, otherwise It will be true atleast in one iteration.
In comments you wrote:
You want to calculate 3 records
instead of using myList, create a separate list (say myChoosenCountriesList) of having those countries only when you want if condition to become true.
Then replace your code with following: (Note other improvments also)
int countryCount = myChoosenCountriesList.size();
for(int zTmp = 0; zTmp<countryCount; zTmp++)
{
String countryName = myChoosenCountriesList.get(zTmp);
System.out.println("COUNTRY IS"+countryName);
if(record.contains(countryName))
{
// my next step
}
}

The desired output has been achieved by using do while loop
here is the snippet
int zTmp=0;
do
{
String country=myList.get(zTmp);
if(inputCountry.equals(country))
{
CalcDays(tmpTokens[iTmp]);
myDateList.clear();
}zTmp++;
}while(zTmp<myList.size());

Related

Manipulating CSV file with a non standardized content

I have a CSV file with a non standardized content, it goes something like this:
John, 001
01/01/2015, hamburger
02/01/2015, pizza
03/01/2015, ice cream
Mary, 002
01/01/2015, hamburger
02/01/2015, pizza
John, 003
04/01/2015, chocolate
Now, what I'm trying to do is to write a logic in java to separate them.I would like "John, 001" as the header and to put all the rows under John, before Mary to be John's.
Will this be possible? Or should I just do it manually?
Edit:
For the input, even though it is not standardized, a noticeable pattern is that the row that do not have names will always starts with a date.
My output goal would be a java object, where I can store it in the database eventually in the format below.
Name, hamburger, pizza, ice cream, chocolate
John, 01/01/2015, 02/01/2015, 03/01/2015, NA
Mary, 01/01/2015, 02/01/2015, NA, NA
John, NA, NA, NA, 04/01/2015
You could just read the file into a list
List<String> lines = Files.readAllLines(Paths.get(path), StandardCharsets.UTF_8);
Afterwards iterate over the list and split them for wanted delimiters (",").
Now you could just use if-else or switch blocks to check for specific entries.
List<DataObject> objects = new ArrayList<>();
DataObject dataObject = null;
for(String s : lines) {
String [] splitLine = s.split(",");
if(splitLine[0].matches("(\d{2}\/){2}\d{4}")) {
// We found a data
if(dataObject != null && splitLine.length == 2) {
String date = splitLine[0];
String dish = splitLine[1];
dataObject.add(date, dish);
} else {
// Handle error
}
} else if(splitLine.length == 2) {
// We can create a new data object
if(dataObject != null) {
objects.add(dataObject);
}
String name = splitLine[0];
String id = splitLine[1];
dataObject = new DataObject(name, id);
} else {
// Handle error
}
}
Now you can sort them into your specific categories.
Edit: Changed the loop and added a regex (which may not be optimal) for matching the date strings and using them to decide whether to add them to the last data object.
The DataObject class can contain data structures holding the dates/dishes. When the CSV is parsed you can iterate over the objects List and do whatever you want. I hope this answer helps :)
If I have correctly understood, the specs are :
input is text, one record per line (fields are comma delimited)
2 kinds of records :
headers consisting of a name and a number (number is ignored)
actual records consisting of a date and a meal
output should contain :
one header containing the constant Name, and the meals in order of occurence
on record per name consisting with the name and the dates corresponding to the meals - an absent field will have NA constant string
we assume that we will never get for a name the same date for different input records.
The algorithm is in pseudo code :
Data structures :
one list of struct< string name, hash< int meal index, date> > for the names : base
one list of strings for the meals : meals
Code :
name = null
iname = -1
Loop per input lines {
if first field is date {
if name == null {
throw Exception("incorrect structure");
}
meal = second field
look for index of meal in meals
if not found {
index = len(meals);
add meal at end of list meals
}
base[iname].hash[index] = date
}
else {
name = first field
iname += 1
add a new struc { name, empty hash } at end of list base
}
}
close input file
open output file
// headers
print "names"
for meal in meals {
print ",", meal
}
print newline
for (i=0; i<=iname; i++) {
print base[i].name
for meal in meals {
look for meal in base[i].hash.keys
if found {
print ",", base[i].hash[meal]
}
else {
print ",NA"
}
}
print newline
}
close output file
Just code it in correct Java and come back here if you have any problem.
Use uniVocity-parsers to handle this for you. It comes with a master-detail row processor.
// 1st, Create a RowProcessor to process all "detail" elements (dates/ingredients)
ObjectRowListProcessor detailProcessor = new ObjectRowListProcessor();
// 2nd, Create MasterDetailProcessor to identify whether or not a row is the master row (first value of the row is a name, second is an integer).
MasterDetailListProcessor masterRowProcessor = new MasterDetailListProcessor(RowPlacement.TOP, detailProcessor) {
#Override
protected boolean isMasterRecord(String[] row, ParsingContext context) {
try{
//tries to convert the second value of the row to an Integer.
Integer.parseInt(String.valueOf(row[1]));
return true;
} catch(NumberFormatException ex){
return false;
}
}
};
CsvParserSettings parserSettings = new CsvParserSettings();
// Set the RowProcessor to the masterRowProcessor.
parserSettings.setRowProcessor(masterRowProcessor);
CsvParser parser = new CsvParser(parserSettings);
parser.parse(new FileReader(yourFile));
// Here we get the MasterDetailRecord elements.
List<MasterDetailRecord> rows = masterRowProcessor.getRecords();
// Each master record has one master row and multiple detail rows.
MasterDetailRecord masterRecord = rows.get(0);
Object[] masterRow = masterRecord.getMasterRow();
List<Object[]> detailRows = masterRecord.getDetailRows();
Disclosure: I am the author of this library. It's open-source and free (Apache V2.0 license).

Looping through List and creating views dependent on the data

I currently have two Lists:
List<String> listUserAnswers = splitWords(answer);
List<String> listRealAnswers = splitWords(realAnswer);
My main goal is to loop through these and create different views dependent on the data. For example, for each correctAnswer I will create one kind of view, and for incorrectAnswer, another.
I then loop through both the Lists:
for (String userAnswer : listUserAnswers) {
for (String realAnswer : listRealAnswers) {
if (userAnswer.equals(realAnswer)) {
correctLayout = createCorrectView(userAnswer);
newCorrectViews.add(correctLayout);
} else {
incorrectLayout = createIncorrectView(userAnswer);
newIncorrectViews.add(incorrectLayout);
}
}
}
I then check if the userAnswer matches the realAnswer, and then create the views.
However, the problem I'm experiencing is that if the realAnswer is:
[This, Is, The, Real, Answer]
and a user enters:
[This, Is, Real]
Then the first two words should show up on the screen as being correct, and the word 'Real' incorrect.
However, what's actually happening is:
[This, Is, This, This, Is, Is, Real, Real] -> where [This, Is] are correct and the rest are marked as incorrect.
Any ideas?
You shouldn't have an inner loop. You just need a loop for both so don't use an enhance one.
You can use something like:
minSize = listUserAnswers.size() > listRealAnswers.size() ? listUserAnswers.size() : listRealAnswers.size();
for(int i = 0; i < minSize; i++)
String userAnswer = listUserAnswers.get(i);
String realAnswer = listRealAnswers.get(i);
if(userAnswer.equals(realAnswer))
....
which just checks for the actual words in the same position.

Copy a string splitted to another string

In some place of a class I have declared a temporal String variable:
String name;
Which I will use to store data from a text. The text have many fields with these two types of format:
Type: text/html
name=foo
For this case, I am particularly interested in the fields of the type name=foo
So, I breaked previously the lines of the text using split
String lines[] = text.split("\n");
And, again, I will use split to identify the fields of the type mentioned. In the code below, the while cycle stops where it detects a name=foo field, and prints the value of that field in the console.
int i = 0; // Counter for the while cycle
while (!(lines[i].split("=")[0].equals("name"))) {
i++;
if (lines[i].split("=")[0].equals("name")) // If the field is name...
System.out.println(lines[i].split("=")[1]); // Prints the value of the field
name = lines[i].split("=")[1]; // <-- My problem is here
}
My problem starts when I want to copy the value of the field to the String variable mentioned early, giving me an java.lang.ArrayIndexOutOfBoundsException.
I need that String to do something with it later. Any idea to safely copy the value of that field to a String variable?
Adding paranthesis to your if saves you from two problems:
if a line contains no = the whole String is in [0] and accessing [1] will result in said Exception
you are changing (overwriting) the variable name regardless of the condition
To please the compiler you may also want to intialize name to something like null.
int i = 0; // Counter for the while cycle
while (!(lines[i].split("=")[0].equals("name"))) {
i++;
if (lines[i].split("=")[0].equals("name")){ // If the field is name...
System.out.println(lines[i].split("=")[1]); // Prints the value of the field
name = lines[i].split("=")[1]; // <-- My problem is here
}
}
In your code:
String name;
name = lines[i].split("=")[1];
Here name will overwrite every time.
I think you are looking for something like this:
String names[];
String lines[] = text.split("\n");
names[] = new String[lines.length];
And inside you while loop do it like:
names[i] = lines[i].split("=")[1];
There are quite a few things to note about your code:
you probably miss {} after the if-statement and therefore update name every run of the while-loop
you access [1] without checking how many elements the split("=") yielded
you literally call split("=") 4 times on almost every line. Save CPU-time by introducing a temporary variable!
you can replace your while-loop by a for-loop which also finds name=value in the first line and does not "throw up" if name=value is not inside any of the lines (you don't check whether i is less than lines.length)
I left your comments inside my answer; feel free to remove them.
Variant a (using an index):
for (int i = 0; i < lines.length; i++) {
// Only split once and keep X=Y together in name=X=Y by specifying , 2
final String[] split = lines[i].split("=", 2);
if (split.length == 2 && split[0].equals("name")){ // If the field is name...
System.out.println(split[1]); // Prints the value of the field
name = split[1]; // <-- My problem is here
break; // no need to look any further
}
}
Variant b (using "for-each"):
for (String line : lines) {
// Only split once and keep X=Y together in name=X=Y by specifying , 2
final String[] split = line.split("=", 2);
if (split.length == 2 && split[0].equals("name")) { // If the field is name...
System.out.println(split[1]); // Prints the value of the field
name = split[1]; // <-- My problem is here
break; // no need to look any further
}
}
I suppose your problem is when you reach the last line or a line which doesn't contains a "=" sign. You are checking
!(lines[i].split("=")[0].equals("name"))
but then you add 1 to i, so maybe this condition now is false
if (lines[i].split("=")[0].equals("name"))
and you will get java.lang.ArrayIndexOutOfBoundsException here
name = lines[i].split("=")[1];
if the line doesn't contains a "=".
Try
if (lines[i].split("=")[0].equals("name")) { // If the field is name...
System.out.println(lines[i].split("=")[1]); // Prints the value of the field
name = lines[i].split("=")[1];
}

Get 2 consecutive rows of a resultset

I need to compare a row of a ResultSet with the consecutive row if the row string matches a particular string.
while(rs.next())
{
String name = rs.getString("name");
if(name.equalsIgnoreCase("SomeName")
{
String nextName = //code to get the next consecutive row
if(nextName.contains(name)
{
name = "NA";
}
}
stringList.add(name);
}
How can I get the next row while the cursor is still on that row?
Approach hint: try storing the first one in a variable and then compare when reading the next row.
Really teaching you how to fish here, not handing you the catch.
To flesh this out (a little):
String lastName = null;
while (rs.next()) {
// do stuff with this row
if (name.equalsIgnoreCase("SomeName") && lastName != null) {
// work with lastName & SomeName
}
// save/assign lastName
}
You can use rs.next(), rs.getString() and then rs.previous() to move one row forward.
However a better option would be to memorize previous string value in a local variable and compare it at the next iteration.
Hint: Try to store first row value then use another loop and compare that value.
Hint: use nested loop

Java Map Matching Key

i am facing a problem which is:
I have map containing string and string. When i print that map i can see that there is a key
"0-8166-3835-7". But when i am trying to get it, there is nothing to get returned, like no matching found...
My code:
//Open a stream to read from file with isbn's AND titles
Scanner IsbnTitle = new Scanner(new FileReader("C:/Users/Proskopos/Documents/NetBeansProjects/ReadUrl/IsbnTitle.txt"));
//Create a Map to save both ISBN's and Titles
Map <String,String> IsbnTitleMap = new HashMap();
while(IsbnTitle.hasNext()){
String recordIsbnTitle = IsbnTitle.nextLine();
UrlFunctions.AddToMap(Recognised , recordIsbnTitle, IsbnTitleMap);
}
.....
.....
Set IsbnSet = new HashSet();
while (IsbnFile.hasNextLine()) {
String isbn = IsbnFile.nextLine();
IsbnSet.add(isbn);
}
//Create an Iterator for IsbnSet
Iterator IsbnIt =IsbnSet.iterator();
String suffix = IsbnIt.next().toString();
String OPACIALtitle = UrlFunctions.GetOpacTitle(suffix, IsbnTitleMap);
The code above is the only part in main about MAP and below are the functions i call:
static String GetOpacTitle(String opIsbn, Map IsbnTitle) {
String OpacTitle = null;
String isbn = opIsbn;
Map isbnMap = IsbnTitle;
System.out.println(isbn);
if ( isbnMap.containsKey(isbn)){
System.out.println("AAAAAAAAAAAAAAAA");
}
//String tade = isbnMap.get(isbn).toString();
//System.out.println("*************" + tade);
return OpacTitle;
}
static void AddToMap(int Recognise, String recordIsbnfollowed, Map IsbnfollowedMap) {
Map isbnsth = IsbnfollowedMap;
String records = recordIsbnfollowed;
int recs= Recognise;
if (recs == 0 || recs == 3) {
String isbn = records.substring(0, 10);
String title = records.substring(10);
isbnsth.put(isbn, title);
// System.out.println(isbn);
}else if (recs == 1) {
String isbn = records.substring(0, 14);
String title = records.substring(14);
isbnsth.put(isbn, title);
// System.out.println(isbn);
}
}
I cant understand where the problem is.. Maybe it is something like encoding of the suffix cames from a set, and the key from a map? they are both string.. dont think so..!!!
So? Can you help?
EDIT: I am trully sorry if you find the code difficult to read :\ I will follow your advices!!
BUT in case that anyone else has the same problem the solution was what Brand said below.. (I re-post it)
You probably have some whitespace in the Strings that you are reading form the file and storing in the Map. If this is the case use String.trim() before storing the value in the Map, and also before querying for the same string. – Brad 3 hours ago
Thank you all
Just to add to my comment that identified the problem. When comparing Keys in a Map you must be very careful about white space and case sensitivity. These types of issues commonly occure when reading data from Files because it's not always obvious what characters are being read. Even looking in your debugger whitepsace cna be an issue.
Always try to "normalize" your data by trimming leading and trailing whitespace before storing it in a Map.

Categories