Java's String.replaceAll not working [duplicate] - java

This question already has an answer here:
Why String.replaceAll() don't work on this String?
(1 answer)
Closed 8 years ago.
I'm building a string that represents a polynomial. I'm trying to replace all ^1 and x^0 with "" to simplify the output using the replaceAll method. However when I run the code, it does not detect any of the target strings.
public String toString() {
String output = "";
boolean isFirst = true;
for(Node current = head; current != null; current = current.next) {
if(isFirst) {
output += current.coefficient + "x^" + current.exponent;
isFirst = false;
}
else if(current.coefficient < 0)
output += " - " + current.coefficient*-1 + "x^" + current.exponent;
else
output += " + " + current.coefficient + "x^" + current.exponent;
}
output.replaceAll("x^0", "");
output.replaceAll("^1", "");
return output;
}

Strings are immutable. You cannot alter a String. As such, the replace and replaceAll methods return a new String. Here try this:
output = output.replaceAll("x^0", "");
output = output.replaceAll("^1", "");

Because Strings are immutable, any modifying operation returns a new string. Thus, you must save and work on with the function result:
output = output.replace(...)
Also, please take a look at the definite spec for allowed patterns: http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
The one point i want to call out is that a ^ at the start of a string anchors the pattern to the beginning of the string. You do not want that, so escape it: \^.
Anyway, you really want to remove the calls to replaceAll: "x^1" matches the beginning of "x^10"! Just don't include those substrings when you build your string.
double f = current.coefficient;
if(isFirst)
isFirst = false;
else if(f < 0) {
f = -f;
output += " - ";
} else
output += " + ";
output += f;
if(current.exponent == 1)
output += "x";
else if(current.exponent != 0)

Strings are immutable. If you look at the documentation, you'll see that every method that modify the content of a String returns a new one.
So you need to assign back the result of replaceAll to output.
output = output.replaceAll("x^0", "");

Related

How to replace special charactes on specific position [duplicate]

This question already has answers here:
Replace a char at Nth position
(3 answers)
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
what I want to do is to replace it with 9 if 3 is written in the 3rd character in a data. But I only want to do this for the 3rd character. How can I do it? This code I wrote replaces all 3's in the string with 9.
Regards...
String adana = "123456789133";
if (adana.length() > 2 && adana.charAt(2) == '3'){
final String newText = adana.replace("3", "9");
Log.d("TAG", "onCreate: " + newText);
}
You can use this:
final String newText = adana.replaceAll("3(?<=^\\d{3})", "9");
The regex I used here uses positive look behind to search for occurrence of 3 in the 3rd position of the string. You can use replaceAll() or replaceFirst() since it accepts regex. Both case works.
Try concatenating substrings:
String adana = "123456789133";
if (adana.length() > 2 && adana.charAt(2) == '3') {
final String newText = adana.substring(0,2) + "9" + adana.substring(3);
Log.d("TAG", "onCreate: " + newText);
}
Your code checks relatively correctly, however you are failing to actually do the replacement. When using the replace() method of a string what java will do is replace all occurrences passed as the first parameter with the value passed in the second parameter. So naturally what you are talking about will happen. One way to solve this in this specific case is to do:
String adana = "123456789133";
StringBuilder newText = new StringBuilder();
for (int i = 0; i < adana.length(); i++) {
if (i == 2 && adana.charAt(2) == '3') {
newText.append('9');
} else {
newText.append(adana.charAt(i));
}
}
This strategy will work for any string of any length.
Or if you don't want to use string builders (which is not recommended in this case), you can do:
String newText = "";
for (int i = 0; i < adana.length(); i++) {
if (i == 2 && adana.charAt(2) == '3') {
newText += "9";
} else {
newText += adana.charAt(i);
}
}

Replace multiple occurences of substring with conditional substring that includes the original substring

Sorry for the long title, but I'm at a loss here as a beginner... possibly I can't find an existing solution because I don't know the terms to search for.
What I'm trying to do is replace all substrings in a string with some conditional substring that includes the original substring. An example might be more clear:
String answerIN = "Hello, it is me. It is me myself and I."
//should become something like:
String answerOUT = "Hello, it is <sync:0> me. It is <sync:1> me myself and I"
So the substring "me" should be replaced by itself plus some conditional thing. What I tried so far doesn't work because I keep on replacing the replaced substring. So I end up with:
String answerOUT = "Hello, it is <sync:0> <sync:1> me. It is <sync:0> <sync:1> me myself and I"
My code:
String answerIN = "Hello, it is me. It is me myself and I.";
String keyword = "me";
int nrKeywords = 2; //I count this in the program but that's not the issue here
if (nrKeywords != 0){
for (int i = 0; i < nrKeywords; i++){
action = " <sync" + i + "> " + keyword;
answerIN = answerIN.replace(keyword, action);
System.out.println("New answer: " + answerIN);
}
}
I can't figure out how to NOT replace the substring-part of the string that was already replaced.
String#replace will allways replace each occurence of the String you are looking for with what you want to replace it with. So that´s not possible with the regular String#replace, as there is no "only replace from here to there".
You could work with the String's substring method in order to replace each occurence:
String input = "Hello, it is me. It is me myself and I.";
String output = "";
String keyword = "me";
int nextIndex = input.indexOf(keyword), oldIndex = 0, counter = 0;
while(nextIndex != -1) {
output += input.substring(oldIndex, nextIndex-1) + " <sync:" + counter + "> ";
oldIndex = nextIndex;
nextIndex = input.indexOf(keyword, nextIndex+1);
++counter;
}
output += input.substring(oldIndex);
System.out.println(output);
O/P
Hello, it is <sync:0> me. It is <sync:1> me myself and I.

Recursion for printing out words in sentence backwards

I'm working on getting a method that prints the words of a sentence out backwards. I'm very close to a solution but am hitting a minor snag.
Here is my code:
public static String reverseString(String str) {
if (str.equals(""))
return "";
else {
int i = str.length() - 1;
while (!Character.isWhitespace(str.charAt(i))) {
if (i - 1 < 0)
break;
i--;
}
return str.substring(i,str.length()) + reverseString(str.substring(0,i));
}
}
Now the problem is the that the output from my test:
String test = "This is a test.";
System.out.println(reverseString(test));
Is giving me this back:
test. a isThis
Now, when I try to bump up the index of the substring being returned and add in the spaces manually, it cuts off the "T" in "This". That is, if I decide to instead return as follows:
return str.substring(i+1,str.length()) + " " + reverseString(str.substring(0,i));
then I get back
test. a is his
Does anyone have any advice or pointers on my implementation in general?
You can change the return statement to this:
return str.substring(i, str.length()).trim() + " " + reverseString(str.substring(0, i));
Split the sentence using String.split and then iterate over the resulting array backwards. To split at whitespace do
test.split(" +");
The split method takes a Regular Expression and the above means: split at one or more consecutive whitespaces.
Recursive approach:
public String reverse(final String s) {
final int pos = s.indexOf(' ');
if (pos > -1) {
return reverse(s.substring(pos + 1).trim()) + " " + s.substring(0, pos).trim();
}
return s;
}
In this approach you can selectively create substring based on whitespace. For input This is a test. below method will give return test. a is This. Idea here is if you have a leading space, you will actually convert to trailing space.
public static String reverseString(String str) {
if (str.equals(""))
return "";
else {
int i = str.length() - 1;
while (!Character.isWhitespace(str.charAt(i))) {
if (i - 1 < 0)
break;
i--;
}
String substring;
if(Character.isWhitespace(str.charAt(i)))
{
substring= str.substring(i+1,str.length())+" ";
}
else
{
substring= str.substring(i,str.length());
}
return substring + reverseString(str.substring(0,i));
}
}
Working with your code you would just need to add an additional space in front of whatever string you want to reverse such as with this code
reverseString(" " + str)
when you first execute the method.

Check if letter x is between two quotes

I'd like to check if some character is between 2 other chars.
For example, given the following String:
String myString = "Hello, my name is 'Tesda', and this is 'ASDfs'."
I want to check if the 'S' in "ASDfs" is between '' or not, also keeping in mind I want to check every '', not jump directly to the second ''.
I've tried a silly code (I'm not familiar with this at all, as I didn't need it until now), which is:
boolean isBetween;
if (!MyString.substring(MyString.indexOf("'"), MyString.indexOf("'")).contains("S"))
isBetween = true;
Well, this didn't work and I don't understand how to make it perfectly.
Also, I want to replace that S with another letter, but I want only between the '', not the one after "my name is", I thought about getting the index of the letter, if it's inside '', then replace that letter in that specific index, is that possible?
Using the provided answer, I've made the following code ( which why i posted this question for ) :
String NewText = "Hello, My NAme is 'Ba', i'm from 'LA' ";
boolean contains = false;
int indexOfS = -1;
String MyString_temp = NewText;
while (MyString_temp.length() >= 0) {
int first = MyString_temp.indexOf("\'");
if(first == -1)
{
break;
}
int second = MyString_temp.substring((first + 1)).indexOf("\'");
second = second + first + 1;
if(second == -1)
{
break;
}
contains = MyString_temp.substring(first,second).contains("A");
if (contains) {
break;
}
MyString_temp = MyString_temp.substring((second + 1));
}
Log.i("ResultTest","Index is: " + indexOfS + " - Text is: " + MyString_temp);
if(!contains){
Log.i("ResultTest", "Yes " + i);
Log.i("ResultTest","TeF: " +NewText.replace(NewText.substring(indexOfS,indexOfS+1),"Test"));
} else
Log.i("ResultTest", "No " + i);
Output
Index is: -1 - the text here ..
Failed to output, invalid index
Consider using regular expressions. Your example could be as simple as
MyString.matches("\'S\'");
EDIT: Updated answer for updated question: Your initial code block looked like it might have done the trick, however you must remember that indexOf() only returns the first occurence of what you need. This could work:
String MyString_temp = MyString;
String lookingFor = "S";
String separator = "\'";
boolean contains = false;
int indexOfLooking = -1;
while (MyString_temp.length() >= 0) {
int first = MyString_temp.indexOf(separator);
if(first == -1) {
break;
}
int second = MyString_temp.substring(first + 1).indexOf(separator);
second += first + 1;
if(second == -1) {
break;
}
indexOfLooking = MyString_temp.substring(first, second).indexOf(lookingFor);
contains = (indexOfLooking >= 0)
if (contains) {
break;
}
MyString_temp = MyString_temp.substring(second + 1);
}
After the while loop, contains has your answer, and indexOfLooking has the location of S.
With Apache Commons you can use the following method:
StringUtils.substringBetween(str, "'");
to get an String[] with all results use this:
StringUtils.substringsBetween(str, "'", "'");

How to extract a multiple quoted substrings in Java

I have a string that has multiple substring which has to be extracted. Strings which will be extracted is between ' character.
I could only extract the first or the last one when I use indexOf or regex.
How could I extract them and put them into array or list without parsing the same string only?
resultData = "Error 205: 'x' data is not crawled yet. Check 'y' and 'z' data and update dataset 't'";
I have a tried below;
protected static String errorsTPrinted(String errStr, int errCode) {
if (errCode== 202 ) {
ArrayList<String> ar = new ArrayList<String>();
Pattern p = Pattern.compile("'(.*?)'");
Matcher m = p.matcher(errStr);
String text;
for (int i = 0; i < errStr.length(); i++) {
m.find();
text = m.group(1);
ar.add(text);
}
return errStr = "Err 202: " + ar.get(0) + " ... " + ar.get(1) + " ..." + ar.get(2) + " ... " + ar.get(3);
}
Edit
I used #MinecraftShamrock 's approach.
if (errCode== 202 ) {
List<String> getQuotet = getQuotet(errStr, '\'');
return errStr = "Err 202: " + getQuotet.get(0) + " ... " + getQuotet.get(1) + " ..." + getQuotet.get(2) + " ... " + getQuotet.get(3);
}
You could use this very straightforward algorithm to do so and avoid regex (as one can't be 100% sure about its complexity):
public List<String> getQuotet(final String input, final char quote) {
final ArrayList<String> result = new ArrayList<>();
int n = -1;
for(int i = 0; i < input.length(); i++) {
if(input.charAt(i) == quote) {
if(n == -1) { //not currently inside quote -> start new quote
n = i + 1;
} else { //close current quote
result.add(input.substring(n, i));
n = -1;
}
}
}
return result;
}
This works with any desired quote-character and has a runtime complexity of O(n). If the string ends with an open quote, it will not be included. However, this can be added quite easily.
I think this is preferable over regex as you can ba absolutely sure about its complexity. Also, it works with a minimum of library classes. If you care about efficiency for big inputs, use this.
And last but not least, it does absolutely not care about what is between two quote characters so it works with any input string.
Simply use the pattern:
'([^']++)'
And a Matcher like so:
final Pattern pattern = Pattern.compile("'([^']++)'");
final Matcher matcher = pattern.matcher(resultData);
while (matcher.find()) {
System.out.println(matcher.group(1));
}
This loops through each match in the String and prints it.
Output:
x
y
z
t
Here is a simple approach (assuming there are no escaping characters etc.):
// Compile a pattern to find the wanted strings
Pattern p = Pattern.compile("'([^']+)'");
// Create a matcher for given input
Matcher m = p.matcher(resultData);
// A list to put the found strings into
List<String> list = new ArrayList<String>();
// Loop over all occurrences
while(m.find()) {
// Retrieve the matched text
String text = m.group(1);
// Do something with the text, e.g. add it to a List
list.add(text);
}

Categories

Resources