java replaceLast() [duplicate] - java

This question already has answers here:
Replace the last part of a string
(11 answers)
Closed 5 years ago.
Is there replaceLast() in Java? I saw there is replaceFirst().
EDIT: If there is not in the SDK, what would be a good implementation?

It could (of course) be done with regex:
public class Test {
public static String replaceLast(String text, String regex, String replacement) {
return text.replaceFirst("(?s)"+regex+"(?!.*?"+regex+")", replacement);
}
public static void main(String[] args) {
System.out.println(replaceLast("foo AB bar AB done", "AB", "--"));
}
}
although a bit cpu-cycle-hungry with the look-aheads, but that will only be an issue when working with very large strings (and many occurrences of the regex being searched for).
A short explanation (in case of the regex being AB):
(?s) # enable dot-all option
A # match the character 'A'
B # match the character 'B'
(?! # start negative look ahead
.*? # match any character and repeat it zero or more times, reluctantly
A # match the character 'A'
B # match the character 'B'
) # end negative look ahead
EDIT
Sorry to wake up an old post. But this is only for non-overlapping instances.
For example .replaceLast("aaabbb", "bb", "xx"); returns "aaaxxb", not "aaabxx"
True, that could be fixed as follows:
public class Test {
public static String replaceLast(String text, String regex, String replacement) {
return text.replaceFirst("(?s)(.*)" + regex, "$1" + replacement);
}
public static void main(String[] args) {
System.out.println(replaceLast("aaabbb", "bb", "xx"));
}
}

If you don't need regex, here's a substring alternative.
public static String replaceLast(String string, String toReplace, String replacement) {
int pos = string.lastIndexOf(toReplace);
if (pos > -1) {
return string.substring(0, pos)
+ replacement
+ string.substring(pos + toReplace.length());
} else {
return string;
}
}
Testcase:
public static void main(String[] args) throws Exception {
System.out.println(replaceLast("foobarfoobar", "foo", "bar")); // foobarbarbar
System.out.println(replaceLast("foobarbarbar", "foo", "bar")); // barbarbarbar
System.out.println(replaceLast("foobarfoobar", "faa", "bar")); // foobarfoobar
}

use replaceAll and add a dollar sign right after your pattern:
replaceAll("pattern$", replacement);

You can combine StringUtils.reverse() with String.replaceFirst()

See for yourself: String
Or is your question actually "How do I implement a replaceLast()?"
Let me attempt an implementation (this should behave pretty much like replaceFirst(), so it should support regexes and backreferences in the replacement String):
public static String replaceLast(String input, String regex, String replacement) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (!matcher.find()) {
return input;
}
int lastMatchStart=0;
do {
lastMatchStart=matcher.start();
} while (matcher.find());
matcher.find(lastMatchStart);
StringBuffer sb = new StringBuffer(input.length());
matcher.appendReplacement(sb, replacement);
matcher.appendTail(sb);
return sb.toString();
}

Use StringUtils from apache:
org.apache.commons.lang.StringUtils.chomp(value, ignoreChar);

No.
You could do reverse / replaceFirst / reverse, but it's a bit expensive.

If the inspected string is so that
myString.endsWith(substringToReplace) == true
you also can do
myString=myString.replaceFirst("(.*)"+myEnd+"$","$1"+replacement)

it is slow, but works:3
import org.apache.commons.lang.StringUtils;
public static String replaceLast(String str, String oldValue, String newValue) {
str = StringUtils.reverse(str);
str = str.replaceFirst(StringUtils.reverse(oldValue), StringUtils.reverse(newValue));
str = StringUtils.reverse(str);
return str;
}

split the haystack by your needle using a lookahead regex and replace the last element of the array, then join them back together :D
String haystack = "haystack haystack haystack";
String lookFor = "hay";
String replaceWith = "wood";
String[] matches = haystack.split("(?=" + lookFor + ")");
matches[matches.length - 1] = matches[matches.length - 1].replace(lookFor, replaceWith);
String brandNew = StringUtils.join(matches);

I also have encountered such a problem, but I use this method:
public static String replaceLast2(String text,String regex,String replacement){
int i = text.length();
int j = regex.length();
if(i<j){
return text;
}
while (i>j&&!(text.substring(i-j, i).equals(regex))) {
i--;
}
if(i<=j&&!(text.substring(i-j, i).equals(regex))){
return text;
}
StringBuilder sb = new StringBuilder();
sb.append(text.substring(0, i-j));
sb.append(replacement);
sb.append(text.substring(i));
return sb.toString();
}

It really works good. Just add your string where u want to replace string in s and in place of "he" place the sub string u want to replace and in place of "mt" place the sub string you want in your new string.
import java.util.Scanner;
public class FindSubStr
{
public static void main(String str[])
{
Scanner on=new Scanner(System.in);
String s=on.nextLine().toLowerCase();
String st1=s.substring(0, s.lastIndexOf("he"));
String st2=s.substring(s.lastIndexOf("he"));
String n=st2.replace("he","mt");
System.out.println(st1+n);
}
}

Related

Java Regex How to Find if String Contains Characters but order is not a matter

I have String like this "abcdefgh"
I want to check the string contains the following characters [fcb]
Condition is : The string must contain all characters in any order.
How to write a regex for this one.
I tried following regexes :
.*[fcb].* ---> In this case it not check all characters. If any one character matchs it will return true
Don't use regex. Just use String.contains to test for each of the characters in turn:
in.contains("f") && in.contains("c") && in.contains("b")
You could get the char arry and sort it. Afterwards you could check if it contains .*b.*c.*f.*.
public static boolean contains(String input) {
char[] inputChars = input.toCharArray();
Arrays.sort(inputChars);
String bufferInput = String.valueOf(inputChars);
// Since it is sorted this will check if it simply contains `b,c and f`.
return bufferInput.matches(".*b.*c.*f.*");
}
public static void main(String[] args) {
System.out.println(contains("abcdefgh"));
System.out.println(contains("abdefgh"));
}
output:
true
false
this will check if all the letters are present in the string.
public class Example {
public static void main(String args[]) {
String stringA = "abcdefgh";
String opPattern = "(?=[^ ]*f)(?=[^ ]*c)(?=[^ ]*b)[^ ]+";
Pattern opPatternRegex = Pattern.compile(opPattern);
Matcher matcher = opPatternRegex.matcher(stringA);
System.out.println(matcher.find());
}
}
You can use positive lookahead for this
(?=.*b)(?=.*c)(?=.*f)
Not very efficient but easy to understand:
if (s.matches(".*b.*") && s.matches(".*c.*") && s.matches(".*f.*"))

Get string within double quotes along with rest of the string

I have a case where I need to extract the string within double quotes in one var and the rest of the string in another var.
Two possibilities:
String: "Franklin B" Benjamin
Result:
var1 = Franklin B
var2 = Benjamin
String: Benjamin "Franklin B"
Result:
var1 = Benjamin
var2 = Franklin B
Regex/Without regex; I am open to any method.
Give this a try...
Basically you remove any leading delimiter in the string before you perform the split. This way you don't have to worry about a leading empty element.
public static void main(String[] args) {
String testString = "\"Franklin B\" Benjamin";
String testString2 = "Benjamin \"Franklin B\"";
displaySplitResults(mySplit(testString, "\""));
displaySplitResults(mySplit(testString2, "\""));
}
private static String[] mySplit(final String input, final String delim)
{
return input.replaceFirst("^" + delim, "").split(delim);
}
private static void displaySplitResults(String[] splitResults) {
if (splitResults.length == 2) {
String var1 = splitResults[0].trim();
String var2 = splitResults[1].trim();
System.out.println(var1);
System.out.println(var2);
}
}
Results:
Franklin B
Benjamin
Benjamin
Franklin B
A simple non-regex way to do it:
public static String[] split(String input) {
if (input.charAt(0) == '"') {
return input.substring(1).split("\" ");
} else {
return input.substring(0, input.length() - 1).split(" \"");
}
}
First check whether the first character is ". Then remove the quote from either beginning or the end and simply split it.
The following will get you a List with the values you want:
private List<String> getValues(String input) {
List<String> matchList = new ArrayList<>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"[^\"]*\"|'[^']*'");
Matcher regexMatcher = regex.matcher(input);
while (regexMatcher.find()) {
matchList.add(regexMatcher.group());
}
return matchList;
}
Taken from Regex for splitting a string using space when not surrounded by single or double quotes
#Shar1er80 Nice piece of work without regex. Worked great.
I also tried with regex:
//Using regex to get values separated by whitespace but keeping values with double quotes
RegexOptions options = RegexOptions.None;
Regex regex = new Regex( #"((""((?<token>.*?)(?<!\\)"")|(?<token>[\w]+))(\s)*)", options );
string input = #" Here is ""my string"" it has "" six matches"" ";
var result = (from Match m in regex.Matches( input )
where m.Groups[ "token" ].Success
select m.Groups[ "token" ].Value).ToList();
Gave me exact result.

Regex replacing specific characters in java

I'm trying to replace some case when I put a generic term (here called tampon).
Rules:
I want to replace "AM into "AN","EM" into "AN", IM"into"IN","OM"into "ON","UM" into "UN" and "YM" into "IN".
I also want to replace them only if a consonant is after them except "M" and "N".
I need to replace only the case too when they are alone or at the end of the string.
I've tried some regex but still got some failures into my test (5/18).
Got faillure with "UMUMMUM" the test expects "UMUMMUM" but I've got "UMUMMUN".
Here is my code now :
public class Phonom {
static String[] consonnant={"B","C","D","F","G","H","J","K","L","P","Q","R","S","T","V","W","X","Z",""};
public static String phonom1(final String tampon){
if (tampon == null){
return "";
}
if (tampon.isEmpty()){
return "";
}
int pos=tampon.indexOf("EM");
int pos1=tampon.indexOf("AM");
int pos2=tampon.indexOf("IM");
int pos3=tampon.indexOf("OM");
int pos4=tampon.indexOf("UM");
int pos5=tampon.indexOf("YM");
if(pos==tampon.length()-2 ||pos1==tampon.length()-2|pos2==tampon.length()-2
||pos3==tampon.length()-2||pos4==tampon.length()-2||pos5==tampon.length()-2){
String temp=tampon.replaceAll("AM","AN");
String temp1=temp.replaceAll("EM","AN");
String temp2=temp1.replaceAll("IM","IN");
String temp3=temp2.replaceAll("OM","ON");
String temp4=temp3.replaceAll("UM","UN");
String result=temp4.replaceAll("YM","IN");
return result;
}
String temp=tampon.replaceAll("AM[^AEIOUMNY]","AN");
String temp1=temp.replaceAll("EM[^AEIOUMNY]","AN");
String temp2=temp1.replaceAll("IM[^AEIOUMNY]","IN");
String temp3=temp2.replaceAll("OM[^AEIOUMNY]","ON");
String temp4=temp3.replaceAll("UM[^AEIOUMNY]","UN");
String result=temp4.replaceAll("YM[^AEIOUMNY]","IN");
return result;
}
}
You could have done this in one line if YM was replaced with YN not IN.
tampon.replaceAll("(?<=[AEIOUY])(M)(?![AEIOUYMN])", "N");
Because of the YM to IN rule you will need to use appendReplacement and appendTail instead. The below code uses a negative look ahead to ensure possible replacements aren't followed by a vowel, M or N. If the first group is a Y we replace the match with IN. If not we use a back reference to the character in group 1 and follow it with an N.
public class Phonom {
private static final Pattern PATTERN = Pattern.compile("([AEIOUY])(M)(?![AEIOUYMN])");
public static String phonom1(String tampon) {
Matcher m = PATTERN.matcher(tampon);
StringBuffer sb = new StringBuffer();
while (m.find()) {
if ("Y".equals(m.group(1))) {
m.appendReplacement(sb, "IN");
} else {
m.appendReplacement(sb, "\1N");
}
}
m.appendTail(sb);
return sb.toString();
}
}

How to get a substring of a certain character followed by a number?

In Java, how would I get a substring of a certain character followed by a number?
The string looks like this:
To be, or not to be. (That is the question.) (243)
I want the substring up until the (243), where the number inside the parenthesis is always changing every time I call.
Use a regular expression:
newstr = str.replaceFirst("\(\d+\)", "");
What this means is to find a substring beginning with (, then any number of digits, and then the character ). Then replace the substring with the empty string, "".
Reference: java.lang.String.replaceFirst()
You could match it with a regex, and get the index of the regex. Then use that to get the index in the string.
An example of that is Can Java String.indexOf() handle a regular expression as a parameter?
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(inputStr);
if(matcher.find()){
System.out.println(matcher.start());//this will give you index
}
You can use String.replaceAll():
String s = "To be, or not to be. (That is the question.) (243)";
String newString = s.replaceAll("\\(\\d+\\).*", "");
I think you can actually just do something like:
mystring.substring(0,mystring.lastIndexOf"("))
assuming that the last thing on the line will be the number in parentheses.
You could use a for loop and add the characters before the number to a separate string
String sentence = "To be, or not to be. (That is the question.) (243)";
public static void main(String[] args) {
String subSentence = getSubsentence(sentence);
}
public String getSubsentence(String sentence) {
String subSentence = "";
boolean checkForNum = false;
for (int i = 0; i < sentence.length(); i++) {
if (checkForNum) {
if (isInteger(sentence.getSubstring(i, i+1))) return subSentence;
checkForNum = false;
} else {
if (sentence.getSubstring(i, i+1).equals("(")) checkForNum = true;
else subSentence += sentence.getSubstring(i, i+1);
}
}
return subSentence;
}
public boolean isInteger(String s) {
try {
Integer.parseInt(s);
} catch(NumberFormatException e) {
return false;
}
return true;
}
Using a regex this can be solved with.
public class RegExParser {
public String getTextPart(String s) {
String pattern = "^(\\D+)(\\s\\(\\d+\\))$";
String part = s.replaceAll(pattern, "$1");
return part;
}
}
Simple and performance is good.

How to compare two Strings in java without considering spaces?

I have one example.
public class Test {
public static void main(String[] args) {
String a="VIJAY KAKADE";
String b="VIJAY KAKADE";
if(a.equalsIgnoreCase(b)){
System.out.println("yes");
}else{
System.out.println("no");
}
}
}
I need to check these strings without considering spaces. How do I achieve this? How do I ignore spaces in the strings when I compare them?
You can try to create a new string by replacing all empty spaces.
if(a.replaceAll("\\s+","").equalsIgnoreCase(b.replaceAll("\\s+",""))) {
// this will also take care of spaces like tabs etc.
}
then compare.
I think replacing all spaces with an empty string poses the danger of verifying the following situation (finding the two names equal):
String a = "ANN MARIE O'RIORDAN"
String b = "ANNMARIE O'RIORDAN"
I know I may be splitting hairs here, but I found this question while looking for a similar solution to verify SQL queries in a unit test. Because my queries are multi-line static final Strings, I wanted to make sure that I didn't miss a space anywhere.
To that end, I think replacing all whitespaces with a single space, or perhaps a special character is the safest solution - which then does require regex:
if (a.trim().replaceAll("\\s+", " ").equalsIgnoreCase(b.trim().replaceAll("\\s+", " "))) {
// Strings equivalent
}
Thoughts?
As Zoltan correctly pointing out, all answers besides his are in fact wrong.
For using the functionality from a third party library I suggest hamcrest:
import static org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace;
public class Main {
public static void main(String[] args) {
String a = "VIJAY KAKADE";
String b = "VIJAY KAKADE";
System.out.print(String.format("'%s' and '%s' matching: ", a, b));
if (equalToIgnoringWhiteSpace(a).matches(b)) {
System.out.println("yes");
} else {
System.out.println("no");
}
String c = "VIJAYKAKADE";
System.out.print(String.format("'%s' and '%s' matching: ", a, c));
if (equalToIgnoringWhiteSpace(a).matches(c)) {
System.out.println("yes");
} else {
System.out.println("no");
}
}
}
returns:
'VIJAY KAKADE' and 'VIJAY KAKADE' matching: yes
'VIJAY KAKADE' and 'VIJAYKAKADE' matching: no
Replace the spaces with empty string:
if (a.replace(" ", "").equalsIgnoreCase(b.replace(" ", "")))
if you want to replace all whitespace, including tabs etc, you can use
a = yourOriginalString.replaceAll("\\s", "");
b = yourOriginalString.replaceAll("\\s", "");
return a.equalsIgnoreCase(b);
edit: woah ninja'd like heck
You can use String.replace() to remove the spaces in both strings.
String aMod = a.replace(" ","");
String bMod = b.replace(" ","");
if( aMod.equalsIgnoreCase(bMod) ){
...
String#replace() method is helpful for you.
public static void main(String[] args) {
String a="VIJAY KAKADE";
String b="VIJAY KAKADE";
a = a.replace(" ", "");
b = b.replace(" ", "");
if(a.equalsIgnoreCase(b)){
System.out.println("yes");
}else{
System.out.println("no");
}
}
a.replace(" ","")
is your best bet. However you can use
a.trim()
to remove leading and trailing whitespaces if you know want to ignore only the leading and trailing whitespaces. Also the StringUtils from apache commons has many more functions to help
public static void main(String args[]) {
String a = "My Name is A B";
String b = "My Name is A B";
System.out.println("Match = " + equalsIgnoreSpace(a, b, false));
}
static boolean equalsIgnoreSpace(String s1, String s2, boolean matchCase) {
String val1 = stripExtraSpaces(s1);
String val2 = stripExtraSpaces(s2);
if(matchCase) {
return val1.equals(val2);
} else {
return val1.equalsIgnoreCase(val2);
}
}
static String stripExtraSpaces(String s) {
String formattedString = "";
java.util.StringTokenizer st = new java.util.StringTokenizer(s);
while(st.hasMoreTokens()) {
formattedString += st.nextToken() + " ";
}
return formattedString.trim();
}

Categories