Sometimes, due to faulty data collected, a line generated by the following method ends up looking like this when saved: ",-1,0" or something similar, with no name, an ID of -1 and a level of 115 or something else. (The lines are formatted like this (excluding quotes): "name,id,level" (e.g: "Honour guard,5514,115")
What i need to do is to remove all strings in monstersToAdd that contains -1.
I've tried this, but with no success:
private void combineInfo() {
for(int i = 0; i < monsterList.size(); i++){
monstersToAdd.add("" + names[i] + "," + IDs[i] + "," + levels[i]);
}
monstersToAdd.remove(monstersToAdd.contains("-1"));
}
with the line monstersToAdd.remove(monstersToAdd.contains("-1")); I was trying to remove all strings in monstersToAdd that contains "-1". This however does not work, probably for good reasons, which I unfortunately don't know of yet.
I would really appreciate any input :).
You would be better off not adding the lines you don't want in the first place.
for (....) {
if (IDs[i] != -1) {
// add it
}
// else it simply doesn't get added
}
More on your original code: You could post a little more detail, such as the type of monsterToAdd. If it is a non-generic list, then the contains method just returns true or false depending if the parameter (here a string of "-1") is present in the list exactly as you pass it, that is it doesn't search for substring matches of the list elements.
remove then tries to remove the element you ask to remove, which may be a Boolean object, automatically boxed from the boolean primitive value returned by contains.
Also, it is suspicious that you have a variable called monsterList which you use for iteration length, but not actually use any elements from that list. Maybe the arrays you use have the same values as the list, and were copied out beforehand? If so, it would be nicer to iterate on the monsterList directly and use its elements.
Its easier if you dont even add them, than adding and removing them so check the sanity of ID names and levels before adding them
private void combineInfo() {
for(int i = 0; i < monsterList.size(); i++){
//add only if name is non empty, ID is not negative and level is below 100
if(!(names[i].isEmpty() || IDs[i]<0 || levels[i]>100))
monstersToAdd.add("" + names[i] + "," + IDs[i] + "," + levels[i]);
}
Why don't you do this instead:
private void combineInfo() {
for(int i = 0; i < monsterList.size(); i++){
if(IDs[i] != -1){
monstersToAdd.add("" + names[i] + "," + IDs[i] + "," + levels[i]);
}
}
monstersToAdd.remove(monstersToAdd.contains("-1"));
}
That way, you never add the monster to the list in the first place, if the ID is -1.
You are really close:
private void combineInfo() {
for(int i = 0; i < monsterList.size(); i++){
if (IDs[i] == -1) continue; // Skip this iteration
monstersToAdd.add("" + names[i] + "," + IDs[i] + "," + levels[i]);
}
}
Filter them out as early as possible rather than back-tracking and removing them.
contains() returns only a true/false result depending on whether the list contains the given input object (in your case the string "-1"). So in your example, your list wouldn't contain "-1", so your remove statement would be resolved to this:
monstersToAdd.remove(false);
which wouldn't work for obvious reasons.
Here is the code:
for(Iterator<String> it = monsterList; it.hasNext();) {
String elem = it.next();
if (elem.contains("-1")) {
it.remove();
}
}
contains() method of collection returns true if collection contains element equals to one passed as an argument. In you case you want to use String's contains() that returns true if the string contains specified substring. This is the reason that you need loop.
This loop must be implemented with iterator. Using new java 5 syntax for(String elem : list) will not work here because you have to remove element. Using for(int i = 0; i < list.size(); i++) requires implementation of logic that safely moves to the next index after element removal.
And the last point. You have to use iterator.remove() instead of Collection.remove() to avoid ConcurrentModificationException
Related
I have a regular for loop that helps me append a character by taking advantage of the index positioning provided by the common for loop.
I want to refactor the loop and turn it into a for each loop, but the disadvantage is the index positioning. I can't find a way to indicate where I want to append my char. Is it even possible to use the for each loop in this case?
from:
for (int i = 0; i < itinerary.size(); i++) {
sb.append(itinerary.get(i).toUpperCase());
if (i < itinerary.size() -1) {
sb.append(" to ");
}
}
to
for (String itineray : itinerary){
sb.append(itineray.toUpperCase());
if ( //size of the array - 1){
sb.append(" to ");
}
}
One option would be to iterate over a subset of the original list which excludes the final element. Then do one additional append afterward.
for (String itineray : itinerary.subList(0, itinerary.size()-1)) {
sb.append(itineray.toUpperCase());
sb.append(" to ");
}
sb.append(itinerary.get(itinerary.size()-1).toUpperCase());
Note that from a performance point of view, this should behave similarly to using an explicit for loop. The only difference is the initial subsetting of the list, but after which point the enhanced loop can run without performing any index checks. And the final append outside the loop would have to happen in any case.
But as #RayToal pointed out, you could use this and avoid the boundary condition problem altogether:
itinerary.stream().collect(Collectors.joining(" to "))
Another way would be to convert to a String and use replace
ArrayList<String> list = new ArrayList<>();
list.add ("one");
list.add ("two");
list.add ("three");
String output = list.toString();
output = output.replace("[", "").replace("]", "").replace(",", " to");
System.out.println(output);
Output
one to two to three
for(int i = 0; i <= gameWord.length()-1; i++)
{
if(guessLetter.charAt(0) == (gameWord.charAt(i)))
{
hideword[i] = guessLetter.charAt(0);
}
else if(guessLetter.charAt(0) != (gameWord.charAt(i)))
{
System.out.print("_" + " ");
}
}
I am making a hangman game and I have created an array list called hideword. Hideword prints an underscore for each letter that is in the word used for the game. I am trying to right a method that will swap the underscore with a letter the user guesses. However this code
hideword[i] = guessLetter.charAt(0);
Doesn't work. It gives me "array required, but java.util.ArrayList found
Anyone help?
Then, hideword must be an arraylist. Use hideword.set(index, character) for assignment instead of accessing it like an array.
An ArrayList is not an array, it's a List implementation (however, its implementation is backed by an array - hence the name).
Declare hideword as an array of char:
private char[] hideword;
and initialize it before use:
hideword = new char[gameword.length];
You code, without changing its basic intention, can be simplified greatly:
There's no need to subtract 1 from the length, just change the comparison operator
There's no need to have your if in the else - we already know it's not equal because we're in the else block
Rather than do useless print, assign an underscore to the array slot
Do one print at the end
Like this:
for (int i = 0; i < gameWord.length(); i++) {
if (guessLetter.charAt(0) == (gameWord.charAt(i))) {
hideword[i] = guessLetter.charAt(0);
} else {
hideword[i] = '_';
}
}
// print hideword
You code would be simpler still if hideword didn't exist and you simply System.out.print() each character as you test it instead.
I searched a code for permutation in java:
public class MainClass {
public static void main(String args[]) {
permuteString("", "String");
}
public static void permuteString(String beginningString, String endingString) {
if (endingString.length() <= 1)
System.out.println(beginningString + endingString);
else
for (int i = 0; i < endingString.length(); i++) {
try {
String newString = endingString.substring(0, i) + endingString.substring(i + 1);
permuteString(beginningString + endingString.charAt(i), newString);
} catch (StringIndexOutOfBoundsException exception) {
exception.printStackTrace();
}
}
}
}
I can't understand it even though I know it was only a basic code. I want someone to explain it to me to make it clearer. Thank you guys
One can construct a permutation, by picking items from a bag repeatedly and thus constructing a sequence. For a string, the bag is a collection of characters. We can use a String to represent this.
If we thus want to construct a random permutated string, we first look if the bag is empty. In the above code, the bag is the endingString and the emptiness check is done with:
if (endingString.length() <= 1)
System.out.println(beginningString + endingString);
As you can see the check does not look whether the bag is completely empty: from the moment the string has only one character (one element), it is evidently we will pick that one. So we pick it and print it after the sequence we've already constructed.
Problem: a problem with this approach is that if we want to list the permutations of the empty string (there is exactly one: the empty string), one will get errors.
Now we need the iterative case. Remember that beginningString stores the sequence we've constructed up till now and endingString stores the list of characters we still can pick from. Now a way to pick is to select a valid index i in the endingString. The character at that index is then picked.
We update the sequence (beginningString by simply appending the character that was placed at i, thus:
beginningString + endingString.charAt(i)
In order to update the bag, it means that the bag now contains all the characters before the index, and the ones after the index. This is formalized as:
String newString = endingString.substring(0, i) + endingString.substring(i + 1);
newString is here the new bag. We can then do the recursive call to pick the next item from the bag. So for a given index i, in order to pick and call recursively, the code reads:
String newString = endingString.substring(0, i) + endingString.substring(i + 1);
permuteString(beginningString + endingString.charAt(i), newString);
Now since we wish to enumerate over all possible permutations, we loop over all possible indices for i. Since we do this recursively as a consequence, we will enumerate all permutations.
Following code written in Java
public static void main (String [] args) throws Exception
{
ordListe ol = new ordListe();
ol.lesBok("navn.text");
ol.leggTilOrd("hello");
ol.leggTilOrd("Hello");
Is my main method. This is about reading from file and adding to a arraylist(dictionary). ''Hello'' and "hello" is supposed to be the same word, and in the code under, it should increase the count of that word.
for (int i = 0; i < ordListe.size(); i++)
{
if (ordListe.toString().contains(s))
{
if (ordListe.get(i).toString().equalsIgnoreCase(s))
{
ord.oekAntall();
System.out.println("'" + s + "' That word is found and there are " + ord.hentAntall() + " of that word now in dictionary.");
break;
}
}
else
{
Ord ny = new Ord(s);
ordListe.add(ny);
System.out.println("'" + s + "' This word is added. " + ny.hentAntall() + " of this word in dictionary.");
break;
}
}
So this is a part of my code. From the main method I add words like ol.leggTilOrd("hello"); leggTilOrd is my method where the code right above is taken from. This is the part of the code that adds words to the dictionary/arrayList and checks if inputwords already exists. I have no problem with anything else than the specific if (ordListe.get(i).toString().equalsIgnoreCase(s)) part. If a word exist in the arrayList, I'm supposed to increase the count of that word. If not, I add the word in the arraylist (ordListe). The problem is that even if I add ol.leggTilOrd("hello") or ol.leggTilOrd("Hello"); with capital 'H', I can't get to recognize it as the same word even if I use the statements above. How do I do this, any other possibilites? This is my last possible effort, after many attempts earlier.
If there are anything questionable above, just tell me.
Change both strings to lower case before comparing and then comapare..it will help you and is easier!!! Use toLower function and then compare
The problem is this line:
if (ordListe.toString().contains(s))
Because 1) you do not compare the lowercase or uppercase versions of the two strings and 2) you probably not overrided toString so it returns the items in the list as you probably expect. Put this function in your ordListe class assuming that your ordliste extends arraylist:
public boolean containsIgnoreCase(String item) {
for(int i = 0; i < size(); i++) {
if (get(i).toString().equalsIgnoreCase(item)) {
return true;
}
}
return false;
}
Now you can call containsIgnoreCase to determinate if there is a specific item in the list ignoring the case
I am creating a program that lets you store 10 items in an array. What I haven't been able to get the program to do is give an error if one of the entered items already exists in the array.
So, for example, if the array looks like [banana, potato, 3, 4, yes, ...] and I enter banana again, it should say "Item has already been stored" and ask me to re-enter the value. The code I currently have is:
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int stringNumber = 0;
String[] stringArray = new String[10];
for (int i = 0; i <= stringArray.length; i++) {
out.println("\nEnter a string");
String input = keyboard.next();
stringArray[stringNumber] = input;
out.println("\"" + stringArray[stringNumber] + "\"" + " has been stored.");
PrintArray(stringArray);
stringNumber++;
You can use nested loops to go through the array to see if the new input exists. It would be better to do this in a function. Also when doing this you need to make sure that you are not at the first element or you will get a null pointer exception.
for (int i = 0; i <= stringArray.length; i++) {
boolean isInArray = false;
System.out.println("\nEnter a string");
String input = keyboard.next();
if (i > 0) {
for (int j = 0; j < stringArray.length; j++) {
if (stringArray[j].equalsIgnoreCase(input)) {
isInArray = true;
break;
}
}
}
if (!isInArray) {
stringArray[stringNumber] = input;
} else {
System.out.println("\"" + stringArray[stringNumber-1] + "\""
+ " has been stored.");
}
PrintArray(stringArray);
stringNumber++;
}
It's always better to use a HashSet when you don't want to store duplicates. Then use HashSet#contains() method to check if element is already there. If ordering is important, then use LinkedHashSet.
If you really want to use an array, you can write a utility method contains() for an array. Pass the array, and the value to search for.
public static boolean contains(String[] array, String value) {
// Iterate over the array using for loop
// For each string, check if it equals to value.
// Return true, if it is equal, else continue iteration
// After the iteration ends, directly return false.
}
For iterating over the array, check enhanced for statement.
For comparing String, use String#equals(Object) method.
When you got the String input, you can create a method that will :
Go through the entire array and check if the string is in it (you can use equals() to check content of Strings)
Returns a boolean value wheter the string is in the array or not
Then just add a while structure to re-ask for an input
Basically it can look like this :
String input = "";
do {
input = keyboard.next();
}while(!checkString(input))
The checkString method will just go through all the array(using a for loop as you did to add elements) and returns the appropriate boolean value.
Without introducing some order in your array and without using an addition structure for instance HashSet, you will have to look through the whole array and compare the new item to each of the items already present in the array.
For me the best solution is to have a helper HashSet to check the item for presence.
Also have a look at this question.
To avoid you should use an Set instead of an array and loop until size = 10.
If you need to keep an array, you can use the .contains() method to check if the item is already present in the array.
while (no input or duplicated){
ask for a new string
if (not duplicated) {
store the string in the array
break;
}
}
You should check the input value in array before inserting into it. You can write a method like exists which accepts String[] & String as input parameter, and find the string into the String array, if it finds the result then return true else false.
public boolean exists(String[] strs, String search){
for(String str : strs){
if(str.equals(search))
return true;
}
return false;
}
performance would be O(n) as it searchs linearly.