I have a method which writes the elements of the array list to a file. The problem is i need a new line for the next 6 consecutive elements in the List.
So the file will look like this.
wrds,wrds,wrds,wrds,wrds,wrds
wrds,wrds,wrds,wrds,wrds,wrds
etc. so the list will look like this:
wrds,wrds,wrds,wrds,wrds,wrds,wrds,wrds,wrds,wrds,wrds,wrds
I need to split the elements by 6 and write them on a new line each time. How do i do this?
public void printToFile()
{
for (int i = 0; i <= one.size(); i++) {
try {
output.write((String)one.get(i));
if (i == 6) {
output.newLine();
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
Everything you need here is an if statement that will evaluate to true for 6th, 12th, 18th... etc. element. You can achieve this using modulo operator (%). i % 6 == 0 will evaluate to true for any ithat is a multiple of 6.
Related
I have two lists in Kotlin, of the same size, foodObjects: MutableList<ParseObject>? and checked: MutableList<Boolean>?. I need to do a for loop and get the objectId from foodObjects every time that an element of checked is true. So it is this in Java:
for (int i = 0; i < foodObjects.size(); i++) {
// here
}
But in Kotlin, I don't know why, there are some problems. In fact, if I do this:
for (i in 0..foodObjects!!.size) {
if (checked?.get(i) == true) {
objectsId?.add(foodObjects.get(i).objectId)
}
}
I've got IndexOutOfBoundsException. I don't know why, it continues the loop also at foodObjects.size. I could do it also with filter and map:
(0..foodObjects!!.size)
.filter { checked?.get(it) == true }
.forEach { objectsId?.add(foodObjects.get(it).objectId) }
but I'm getting the same error. I use this to stop the error and get it to work:
for (i in 0..foodObjects!!.size) {
if (i < foodObjects.size) {
if (checked?.get(i) == true) {
objectsId?.add(foodObjects.get(i).objectId)
}
}
}
Everyone could tell me why in Kotlin I need to do it, when in Java it works good?
Ranges in Kotlin are inclusive, therefore 0..foodObjects!!.size starts at 0 and ends at foodObjects.size, including both ends. This causes the exception when your loop attempts to index the list with its own size, which is one more than the largest valid index.
To create a range that doesn't include the upper bound (like your Java loop), you can use until:
for(i in 0 until foodObjects!!.size) {
// ...
}
You could also clean your code up a bit if you did null checks on the collections you're using up front:
if (foodObjects != null && checked != null && objectsId != null) {
for (i in 0 until foodObjects.size) {
if (checked.get(i) == true) {
objectsId.add(foodObjects.get(i).objectId)
}
}
}
else {
// handle the case when one of the lists is null
}
And to get rid of having to handle indexes altogether, you can use the indices property of a list (plus I use the indexing operator here instead of get calls):
for (i in foodObjects.indices) {
if (checked[i]) {
objectsId.add(foodObjects[i].objectId)
}
}
You could also use forEachIndexed:
foodObjects.forEachIndexed { i, foodObject ->
if (checked[i]) {
objectsId.add(foodObject.objectId)
}
}
Take a look at this example from the Kotlin documentation for ranges:
if (i in 1..10) { // equivalent of 1 <= i && i <= 10
println(i)
}
As you can see
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
will be printed. So, the 10 is included.
The highest index of your collection foodObjects is (foodObjects.size() - 1) because it starts with 0.
So, to fix your problem, just do this:
for(i in 0..(foodObjects.size - 1)) {
// ...
}
A better way to write this would be:
for((i, element) in foodObjects.withIndex()){
// do something with element
println("The index is $i")
}
This way you have the element and the index at once and don't need to worry about ranges.
*I removed the null checks for simplicity.
Here are various ways to ensure the index is valid:
if (index in myList.indices) {
// index is valid
}
// The rangeUntil operator (..<) is still exprimental in Kotlin 1.7.20
if (index in 0..<myList.size) {
// index is valid
}
if (index in 0 until myList.size) {
// index is valid
}
if (index in 0..myList.lastIndex) {
// index is valid
}
if (index >= 0 && index <= myList.lastIndex) {
// index is valid
}
// Note: elements of the list should be non-null
if (myList.getOrNull(index) != null) {
// index is valid
}
// Note: elements of the list should be non-null
myList.getOrNull(index)?.let { element ->
// index is valid; use the element
}
I have a list of class type which holds value from object of class type in following way
public List<Vacc_vs6> refarray_vac1(String fdate,String ldate) throws SQLException, ParseException {
st_jsp.clear();
try {
con = getConnection();
stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
String vs1 = "sql query";
stmt.executeQuery(vs1);
rs = stmt.getResultSet();
while (rs.next()) {
Vacc_vs6 ref = new Vacc_vs6();
ref.setLogtime(rs.getString(1));
ref.setBeam_current(rs.getString(2));
ref.setBeam_energy(rs.getString(3));
ref.setst4_vs6_bag1_rb(rs.getString(4));
ref.setst4_vs6_bag2_rb(rs.getString(5));
ref.setst4_vs6_bag3_rb(rs.getString(6));
ref.setst4_vs6_bag4_rb(rs.getString(7));
ref.setst4_vs6_bag5_rb(rs.getString(8));
ref.setst4_vs6_bag6_rb(rs.getString(9));
ref.setst4_vs6_bag7_rb(rs.getString(10));
ref.setst4_vs6_bag8_rb(rs.getString(11));
ref.setst4_vs6_bag9_rb(rs.getString(12));
st_jsp.add(ref);
}
} catch (Exception e) {
System.out.println("\nException in refarray_vac1 " + e);
}
return st_jsp;
}
st_jsp is the list.
Now I take another list of of class type and want to add values into it corresponding to every column of list st_jsp. I also want to add only those values in the second list which satisfy the given if condition otherwise go to else and put null at particular columns.
For this the code is-
List<Vacc_vs6> new_list=new ArrayList<Vacc_vs6>();
double is = 9.5;
double js = 10.5;
int no=0;
for (no=0;no<st_jsp.size();no++) {
String i= st_jsp.get(no).getBeam_current();
double im = Double.parseDouble(i) ;
if(im>is && im<js) {
new_list.addAll(st_jsp);
} else {
new_list.addAll(null);
}
is +=10;js +=10;
}
Problem-1--> how to add all the 12 columns corresponding to that index in new_list.addAll(???); Did I have to add column where I put ??
ref.setLogtime(rs.getString(1));
ref.setBeam_current(rs.getString(2));
Problem-2 for(no=0;no<st_jsp.size();no++) loop will go till the size of st_jsp but if I do so then all values of st_jsp list will not be displayed because of else condition as I have to add 0 or null to those rows which do not satisfy the above if condition. What to do for this?
1 Problem-1--> **how to add all the 12 columns corresponding to that index in new_list.addAll(???);**Did I have to add column where I put ??
To add only the object that satisfies your condition to the new list you should do:
if (im > is && im < js) {
new_list.add(st_jsp.get(no));
}
The method addAll() adds all elements from one collection into another. So, the way you are doing it, the first time your condition is satisfied you are adding every ref in st_jsp to new_list. And then you will keep re-adding the elements everytime new_list.addAll(st_jsp) is called. Using add() will add only the object you want.
2) Problem-2 for(no=0;no<st_jsp.size();no++) loop will go till the size of st_jsp but if I do so then all values of st_jsp list will not be displayed because of else condition as I ahve to add 0 or null to those rows whcih do not satisfy the above if condition.What to do for this
You are doing the same action in else that you are doing when the if condition is satisfied, that is, adding all elements from st_jsp to new_list:
if (im > is && im < js) {
new_list.addAll(st_jsp);
} else {
new_list.addAll(st_jsp);
}
This means that, after your loop, you will end with st_jsp.size() copies of st_jsp in new_list.
If you need to add an object containing null in all fields to new_list everytime an object does not satisfy your condition you first need to create this object, and then add it when the condition is not met. Also, if you need to test for each element in st_jsp if it satisfies the conditions for all values of is and js, you need to place another loop inside the for loop.
List<Vacc_vs6> new_list = new ArrayList<Vacc_vs6>();
for (int no=0; no < st_jsp.size(); no++) {
double is = 9.5;
double js = 10.5;
double im = Double.parseDouble(st_jsp.get(no).getBeam_current());
// flag to check if an element was added to new_list
boolean added = false;
while (is < 209.9 && js < 210.5) {
if (im > is && im < js) {
new_list.add(st_jsp.get(no));
added = true;
break;
}
is += 10;
js += 10;
}
if (!added) {
// If the element was not added, add an empty object,
// assuming that no field is set when creating the object.
new_list.add(new Vacc_vs6());
}
}
I've been trying to get this to work for a while. I'm putting in three parallel empty arrays and it errors out saying that there is no line found. It ONLY works when I change the while statement to the number of elements. I am trying to make arrays that are the size of 15, but only fill the first ten array portions.
Sorry if it sounds complicated, but basically I'm trying to say that the size of the array is 15, I only have 10 things to enter in the array, and the rest of them should be blank.
while (text.hasNext() && c < nameArray.length) {
nameArray[count] = text.nextLine();
intArray[count] = text.nextDouble();
doubleArray[count] = text.nextInt();
text.nextLine();
c++;
}
This does not work.
while (text.hasNext() && c < 9) {
nameArray[count] = text.nextLine();
intArray[count] = text.nextDouble();
doubleArray[count] = text.nextInt();
text.nextLine();
c++;
}
This does.
Your read the file TWICE within a single loop. Remove the 2nd read:
fileText.nextLine();
Of course it doesn't work. If you need to cycle to the max between fileText length and gameArray length, you should use or instead of and and use an if in the loop.
Try something like this:
while (fileText.hasNext() || count < gameArray.length) {
if (!fileText.hasNext()) {
gameArray[count] = "";
priceArray[count] = 0;
stockArray[count] = 0;
} else {
gameArray[count] = fileText.nextLine();
priceArray[count] = fileText.nextDouble();
stockArray[count] = fileText.nextInt();
fileText.nextLine();
}
count++;
}
Your issue is not with the length of the array but with fileTest.nextLine(). After a certain point there is no nextLine() available. It works for the 1st 9 times but I guess all the lines are exhausted before you reach array.length. I would suggest just one condition in your while loop:
while(fileText.hasNext()) {
}
This way you would fill in only the amount actually present.
Add another check with the second fileText.nextLine() to ensure that there is a line to read.
while (fileText.hasNext() && count < gameArray.length) {
gameArray[count] = fileText.nextLine();
priceArray[count] = fileText.nextDouble();
stockArray[count] = fileText.nextInt();
if ( fileText.hasNext() )
fileText.nextLine();
count++;
}
In the first version of your code, your try to read input 15 times, but it is entered only 10 times. So the scanner tries to read a new line but it doesn't exist.
COMMENTS BELOW ARE ANSWERING ANOTHER QUESTION, THIS IS THE ONLY WAY FOR ME TO ASK NEW QUESTION...
Okay. My program is like writing info on a .txt file. Currently it is writing info to end of the text file like so:
t/1/15/12
o/1/12/3
o/2/15/8
... (lots of lines like this.. all with different numbers)
o/1/16/4
Then.. when I add line using:
BufferedWriter fw = new BufferedWriter(new FileWriter(new File("C://Users/Mini/Desktop/Eclipse/Japda/map/" +Numbers.map +".txt"), true));
fw.newLine();
fw.write(RightPanel.mode.charAt(0) +"/" +ID +"/" +Numbers.middlex +"/" +Numbers.middley);
fw.close();
It adds the line I want to but currently to the end of the text file.. However I would like it to write that line to a specific part of the text files.. I already do know the number of the line I want to write it.. (It is calculated depending on other lines..) :D Is there any way to do it? Or what would be the best way to edit one specific line in the middle of that text file?
To achieve what you require, you would need to use a RandomAccessFile. Steps:
First create a RandomAccessFile then:
Create a variable called lineStart which is initially set to 0
(beginning of the file)
Read in the file line by line using readline
Check whether it is the required line that you wish to insert before
If it is the correct place, then lineStart will hold the position
just before the line you wish to insert before. Use seek to
position you at the correct place by initially using seek(0) to
position you at the start of the file, then seek(lineStart) to get
the required position. You then use writeChars to write to the file.
Remember that you have to explicitly write the newline.
If it is not where you wish to insert then call getFilePointer, and
store value in lineStart
REPEAT STEPS 2-5 UNTIL YOU ARRIVE AT THE DESIRED PLACE FOR INSERTION
You want a do-while loop:
do {
//code
} while (expression);
Source:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/while.html
You probably want something like this:
int[] done = new int[100];
int randomquestion;
do{
randomquestion = (int)(Math.random() * 83 + 1);
if(done[randomquestion] != 1)
{
//ask random question
//if answer is correct, set done[randomquestion] = 1
//else just let do-while loop run
}
//check if all questions are answered
} while (!areAllQuestionsComplete(done));
Here is the method areAllQuestionsComplete(int[]):
private boolean areAllQuestionsComplete(int[] list)
{
for(int i = 0; i<list.length; i++)
{
if(list[i] != 1)
{
return false;//found one false, then all false
}
}
return true;//if it makes it here, then you know its all done
}
Looking at your latest code:
for(int i = 0; i<done.length; i++)
{
done[i] = 0;//need default values else wise itll just be NULL!!!
}
do{
ran = (int)(Math.random() * 83 + 1);
//before entering the do-while loop, you must set default values in the entire done[] array
if(done[ran] != 1)
{
//ask random question
//if answer is correct, set done[ran] = 1
//else just let do-while loop run
if (ran == 1) { //1
question = "kala";
rightanswer = "fish";}
if (ran == 2) { //2
question = "peruna";
rightanswer = "potato";}
if (ran == 3) { //3
question = "salaatti";
rightanswer = "cabbage";}
if (ran == 4) { //4
question = "kalkkuna";
rightanswer = "turkey";}
if (ran == 5) { //5
question = "kia";
rightanswer = "tikku";}
//YOU MUST HAVE EVERY CONDITION COVERED
//say your random number makes the number 10
//you dont set question to anything at all (hence getting null!)
System.out.println(question);
System.out.print("Vastaus?: ");
answer = in.readLine();
//if (answer == rightanswer){
//must use .equals with Strings...not ==
if (answer.equals(rightanswer)){
right++;
done[ran] = 1;}
else{wrong++;}
}
//check if all questions are answered
} while (!areAllQuestionsComplete(done));//use the method I wrote!
EDIT:
You must put default values in the array. When you create an array, the default value is null.
int[] done = new int[100];//create array but everything is null
for(int i = 0; i<done.length; i++)
{
done[i] = 0;//need default values else wise it'll just be NULL!!!
}
//must be done before the do-while loop starts
Finally, make sure your random number generator picks the correct range in numbers. If you have an array that is size 100, then it's indexes will be 0-99. This means there is no done[100]. It goes from done[0] to done[99].
If you have done[] be a size of 5, then it will range from done[0] to done[4]. That means you should randomly generate like this:
randomquestion = (int)(Math.random() * 5 );
i have recrusive function which works fine. The problem is it gives stackoverflow error when the number of lines are huge. I want to put it in iterative, probably using a for loop. Need some help in doing it.
private TreeSet validate(int curLine, TreeSet errorSet) {
int increment = 0;
int nextLine = 0;
if (curLine == lines.length || errorSet.size() != 0) {
return errorSet;
} else {
String line = lines[curLine];
//validation starts. After validation, line is incremented as per the requirements
increment = 1 //As per requirement. Depends on validation results of the line
if (increment > 0) {
try{
Thread.currentThread().sleep(100);
}catch(Exception ex){
System.out.println(ex);
}
nextLine = (curLine + increment);
validate(nextLine, errorSet);
}
}
return errorSet;
}
Poster's description of the method:
The method does validates textlines, these lines has instructions of how much line has to be skipped, if the line is valid. So, if the line is valid that many of lines will be skipped using the increment. if the line is not valid increment will be 0.
I'm not sure why this was ever recursive in the first place. This is perfectly suited for the use of a FOR loop. use something like so:
private TreeSet validate(int curLine, TreeSet errorSet) {
int increment = 0;
if (errorSet.size() != 0)
return errorSet;
for (int curLine = 0; curLine < lines.Length; curLine += increment)
{
// put your processing logic in here
// set the proper increment here.
}
}
If the increment is always going to be 1, then you can just use curr++ instead of curLine += increment
for(String line : lines) {
// validate line here
if(!errorSet.isEmpty()) {
break;
}
}
The solution for your problem could be simple for loop or while, with logical expression for stop condition. Typically we use for loop when we have to pass through all elements of Iterable or array. In case when we are not aware how many loops we are going to do we use a while loop. Advantage of for loop over while, is that we for free have localized variables so we ca not use them out side of the loop, therefore we reduce possibility to have some bug.
You problem is that you have to break the program on two conditions:
When errorSet is not empty.
When the array of lines have no longer items.
As contradiction, we can say that your program should continue:
Until errorSet is empty,
and until line number is smaller than array size where they are stored.
This provide us to simply expression
errorSet.isEmpty()
lineNumber < lines.length()
We can combine them using logical operator && and use as a stop rule in for loop.
for(int lineNumber= 0; errorSet.isEmpty() && lineNumber< lines.length(); lineNumber++) {
//code to operate
}
Note:
Typically for logical expression is used operator &&, that assure that every part of the logical expression is evaluated. An alternative for this is &, that in case of false do not operate longer and return false. We could be tempted to use this operator for this expression but i would be bad idea. Because when we would traversed all lines without error code will generate IndexOutOfBoundException, if we switch the places then we would not have any optimization as first expression would be evaluated same number of times.