Picking out the right characters of a String; - java

I'm trying to pick out the characters of a string that come just before and just after the part of the string that matches another string, creating a completely different string. I.e. when the method wordEnds(String str, String word) is called, and str = "XY1XY" and word = "XY", then the new string would be "11".
Here is what I have so far:
package codingBat;
public class CodingBat {
public static String wordEnds(String str, String
word) {
String newStr = null;
if(str.equals(word)) {
return "";
}
else if(!str.contains(word)) {
return "";
}
else {
for(int i = 0;i < str.length();i++) {
if((word.equals(str.substring(i,i+1)))){
newStr = newStr + (str.substring(i-1,i+2));
}
else {
return newStr;
}
}
return newStr;
}
}
}

Try to use regex, pattern for your example ll look like this XY.*XY. But You have to change the XYto the string parameter so it ll be pattern = str+"(.*)"+str. Then you can use the group and read the string from middle
Here is a code:
static String middleString(String str, String word) {
Pattern pattern = Pattern.compile(str + "(.*)" + str);
Matcher matcher = pattern.matcher(word);
matcher.matches();
return matcher.group(1);
}
This call:
System.out.println(middleString("XY", "XY11XY"));
Returns 11

Related

What is equivalent to .replaceSecond or .replaceThird?

In this code, we remove the substring "luna" from email string using the .replaceFirst method. We are removing the characters in between + and #. But this happens only in the first instance because we used .replaceFirst. What if we wanted to target the second instance of + and # to remove "smith"?
Our output now is alice+#john+smith#steve+oliver# but we want alice+luna#john+#steve+oliver#
public class Main {
public static void main(String[] args) {
String email = "alice+luna#john+smith#steve+oliver#";
String newEmail = email.replaceFirst("\\+.*?#", "");
System.out.println(newEmail);
}
}
You can find the second + like so:
int firstPlus = email.indexOf('+');
int secondPlus = email.indexOf('+', firstPlus + 1);
(You need to handle the case that there aren't two +s to find, if necessary).
Then find the following #:
int at = email.indexOf('#', secondPlus);
Then stitch it back together:
String newEmail = email.substring(0, secondPlus + 1) + email.substring(at);
or
String newEmail2 = new StringBuilder(email).delete(secondPlus + 1, at).toString();
Ideone demo
Unfortunately Java doesn't have methods like replace second, replace third etc. You can either replaceAll (which will replace all occurences) OR invoce replaceFirst again on the already replaced string. That's basically replacing the second. If you want to replace ONLY the second - then you can do it with substrings or do a regex matcher and iterate on results.
public static void main(String[] args) {
String email = "alice+luna#john+smith#steve+oliver#";
String newEmail = email.replaceFirst("\\+.*?#", "");
newEmail = newEmail .replaceFirst("\\+.*?#", ""); //this replaces the second right? :)
newEmail = newEmail .replaceFirst("\\+.*?#", ""); // replace 3rd etc.
System.out.println(newEmail);
}
You can alternate value of parameter n in following replaceNth method to 2, 3 to perform exactly the same operation as that of replaceSecond or replaceThird. ( Note: this method can be applied in any other value of n. If nth pattern do not exist , it simply return given string ).
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static String replaceNth(String str, int n, String regex, String replaceWith) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
while (m.find()) {
n--;
if (n == 0) {
return str.substring(0,m.start() + 1)+ replaceWith + str.substring(m.end() - 1);
}
}
return str;
}
public static void main(String args[]) {
String email = "alice+luna#john+smith#steve+oliver#";
System.out.println(replaceNth(email, 2, "\\+.*?#", ""));
}
}
I think it is better to encapsulate this logic into separate method, where String and group position are arguments.
private static final Pattern PATTERN = Pattern.compile("([^+#]+)#");
private static String removeSubstringGroup(String str, int pos) {
Matcher matcher = PATTERN.matcher(str);
while (matcher.find()) {
if (pos-- == 0)
return str.substring(0, matcher.start()) + str.substring(matcher.end() - 1);
}
return str;
}
Additionally, you can add more methods, to simplify using this util; like removeFirst() or removeLast()
public static String removeFirst(String str) {
return removeSubstringGroup(str, 0);
}
public static String removeSecond(String str) {
return removeSubstringGroup(str, 1);
}
Demo:
String email = "alice+luna#john+smith#steve+oliver#";
System.out.println(email);
System.out.println(removeFirst(email));
System.out.println(removeSecond(email));
System.out.println(removeSubstringGroup(email, 2));
System.out.println(removeSubstringGroup(email, 3));
Output:
alice+luna#john+smith#steve+oliver#
alice+#john+smith#steve+oliver#
alice+luna#john+#steve+oliver#
alice+luna#john+smith#steve+#
alice+luna#john+smith#steve+oliver#
Ideone demo

How can I check whether a string contains a given string, that is not a part of another given string?

For instance, I have this string: hello world, you're full of weird things
I'd like to know whether this string contains a ll that's not a part of the string hell, aka it should return true in this example, because there's a ll in the word full;
If the string was only hello world, it wouldn't match, since the ll in hello is a part of the given hell string
Can you try this:
String mainString = "hello world, you're full of weird things";
String findString = "ll";
String removeString = "hell";
String newString = mainString.Remove(mainString.IndexOf(removeString), removeString.Length);
if (newString.Contains(findString))
{
return true;
}
You could use RegExp and Negative Lookbehind:
public static boolean matches(String str) {
final Pattern pattern = Pattern.compile("(?<!he)ll");
Matcher matcher = pattern.matcher(str);
return matcher.find();
}
Test:
System.out.println(matches("hello world, you're full of weird things")); // true
System.out.println(matches("hello world")); // false
regex101.com
public static boolean checkOccurance(String str,String findStr,,String butNotIn ){
int lastIndex = 0;
int count = 0;
str = str.replace(butNotIn,"");
while(lastIndex != -1){
lastIndex = str.indexOf(findStr,lastIndex);
if(lastIndex != -1){
count ++;
lastIndex += findStr.length();
}
}
if(count>1){
return true;
}else{
return false;
}
call the method
System.out.println( checkOccurance("hello world, you're full of weird things","ll","hell"));
output
false
Why not trying to find the boundary (start and end index) of the butNotIn then use String#indexOf until you have an index that is outside the boundary ?
boolean isIn(String string, String word, String butNotIn) {
int start = string.indexOf(butNotIn);
int end = start+butNotIn.length;
int position;
do {
position = string.indexOf(word);
} while (position<start || position>end);
return position>-1;
}

remove extra letters and numbers from parenthesis in a string

I have a string like:
(aeiou 123) word one
How can I remove everything from the parenthesis so that only "word one" remains?
You could use a regex, e.g.:
String str = "(aeiou 123) word one";
str = str.replaceAll("\\([^\\)]*\\)", "").trim();
public class ParanthesisRemoval {
public static void main(String args[])
{
String test="ab(xy)cd(zw)ef";
boolean modified = true;
while(modified)
{
modified = false;
int indexOpenParanthesis = test.indexOf("(");
int indexClosedParanthesis = test.indexOf(")");
if(indexOpenParanthesis!=-1 && indexClosedParanthesis!=-1 && indexOpenParanthesis<indexClosedParanthesis)
{
int stringLength = test.length();
test = test.substring(0, indexOpenParanthesis)+test.substring(indexClosedParanthesis+1, stringLength);
modified=true;
}
}
System.out.println(test);
}
}
note that this will not work for nested parantesis - (()), or paranthesis not properly paired (()

My custom find-and-replace code not working properly

I've create two custom find-and-replace methods, but they're not working properly.
This is my find-and-replace code:
public final class StringTools {
public static String replaceAll(String text, String replace, String replacement) {
if (replace == replacement)
return text;
String currentText = null;
String newText = text;
do {
currentText = newText;
newText = replaceFirst(newText, replace, replacement);
} while (currentText != newText);
return newText;
}
public static String replaceFirst(String text, String replace, String replacement) {
int found = 0;
int foundAt = -1;
// Loop through each char
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
// Does char match replace char?
if (replace.charAt(found) == c) {
// We found another match
found++;
// Have we found the entire replace text?
if (found == replace.length()) {
// Mark location we found match first at
foundAt = i - found + 1;
break;
}
}
}
// Did we get a match?
if (foundAt != -1) {
// Replace text
return text.substring(0, foundAt) + replacement + text.substring(foundAt + replace.length(), text.length());
}
return text;
}
}
Most of my attempts to try this code gave successful results. However, I found a case where my code fails, but I'm not sure why...
Here's that code:
public static void main(String[] args) {
String text = "{r}0{0}/{r} 10 players";
text = StringTools.replaceAll(text, "{0}", "[test]");
System.out.println(text);
}
However, this outputs:
{r}0[test]/[test] 10 players
As you can see, it replaces the first '{0}' like expected, but for some reason it also replaces the '{r}'.
Any help would be greatly appreciated! Cheers! :)

How to replace a regexp group with a post proceed value?

I have this code to
public static String ProcessTemplateInput(String input, int count) {
Pattern pattern = Pattern.compile("\\{([^\\}]+)\\}");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
String newelem=SelectRandomFromTemplate(matcher.group(1), count);
}
return input;
}
Input is:
String s1 = "planets {Sun|Mercury|Venus|Earth|Mars|Jupiter|Saturn|Uranus|Neptune}{?|!|.} Is this ok? ";
Output example:
String s2="planets Sun, Mercury. Is this ok? ";
I would like to replace the {} set of templates with the picked value returned by the method. How do I do that in Java1.5?
Use appendReplacement/appendTail:
StringBuffer output = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(output, SelectRandomFromTemplate(matcher.group(1), count));
}
matcher.appendTail(output);
return output.toString();

Categories