Lets say I have a string "aabbccaa". Now I want to replace occurrences of "aa" in given string by another string. But it should be in following way.
First occurrence of "aa" should be replaced by "1" and next occurrence of "aa" by "2" and so on.
So, the result of the string becomes "1bbcc2".
You can use replaceFirst() in a for loop where counter is incrementing...
for (int i = 1; string.contains("aa"); i++) {
string = string.replaceFirst("aa", "" + i);
}
You can do it using the Matcher's appendReplacement method:
Pattern p = Pattern.compile("aa");
Matcher m = p.matcher("aabbccaahhhaahhhaaahahhahaaakty");
StringBuffer sb = new StringBuffer();
// Variable "i" serves as a counter. It gets incremented after each replacement.
int i = 0;
while (m.find()) {
m.appendReplacement(sb, ""+(i++));
}
m.appendTail(sb);
System.out.println(sb.toString());
This approach lets you avoid creating multiple string objects (demo).
It is possible to do using Java functions but using a char array and doing it using a lower level of logic would be faster.
String s = "aabbccaa";
String target = "aa";
int i = 1;
String newS;
for (int j = 0; j < s.length; j++) {
newS = s.replaceFirst(target, i++);
j += newS.length - s.length;
s = newS;
}
Here is a solution :
public static void main(String[] a) {
int i = 1;
String before = "aabbccaabbaabbaa";
String regex = "aa";
String after = substitute(i, before, regex);
System.out.println(after);
}
private static String substitute(int i, String before, String regex) {
String after = before.replaceFirst(regex, Integer.toString(i++));
while (!before.equals(after)) {
before = after;
after = before.replaceFirst(regex, Integer.toString(i++));
}
return after;
}
Output :
1bbcc2bb3bb4
Related
String s1 = "aabbccaa";
String s2 = "aa";
I need to count how many times s2 repeated in s1. I tried split text with no luck. Can someone help?
String s1 ="aabbccaa";
String s2 = "aa";
int count = 0;
for(int i = 0; i < s1.length(); i++) {
for(int j = 0; j < s2.length(); j++) {
if(s1.charAt(i) == s2.charAt(j)) {
count++;
}
}
}
System.out.println(count);
}
}
public class Solution {
public static void main(String[] args) {
String s1 ="aabbccaassssASaatestaa";
String s2 = "aa";
// split the string S1 by s2
String a[] = s1.split(s2);
//Output will be 4 - because 'aa' 4 times in s1
System.out.println(a.length);
}
}
Output - 4
In case of overlapping you can use the 'matcher' to get the count of match string in other.
https://www.tutorialspoint.com/javaregex/javaregex_matcher_replaceall.htm
String s1 ="aaaassssaassaass";
String s2 = "aa";
Pattern pattern =Pattern.compile(s2);
Matcher matcher = pattern.matcher(s1);
int i = 0;
while(matcher.find()){
i++;
}
//Out put will be 4
System.out.println(i);
Working Demo
I use Regex. Not sure if this is what you want
Create a parttern from input s2 and match it with s1.
Match will create a list matcher and count it which is the answer.
public int countString(String s1, String s2) {
Pattern pattern = Pattern.compile(s2);
Matcher matcher = pattern.matcher(s1);
int count = 0;
while (matcher.find()) {
count++;
}
return count;
}
Output is 2
You can use the indexOf method.
String indexOf(String str) : This method returns the index within this string of the first occurrence of the specified substring. If it does not occur as a substring, -1 is returned.
I have a string which looks something like this(the most basic form):
String str = "1.0.0.190"
The str can be something like this as well:
1.11.0.12 or 2.111.1.190 or 1.0.0.0
I want to split the string at the 2nd occurrence of the dot(.). How can I achieve that ?
Output:
String str = "1.0.0.190"
String output = "1.0"
I'd fit the answer to OP's level, so I wouldn't recommend split or regexps to him...
If you need substring to second dot, simply find second dot and cut the string to that position...
public class DotSubstring {
public static void main(String[] args) {
String s = "1.2.3.4";
int secondDotPosition = findSecondDotPosition(s);
if (secondDotPosition > 0) {
System.out.println(s.substring(0, secondDotPosition));
} else {
System.out.printf("ERROR: there is not a 2nd dot in '%s'%n", s);
}
}
private static int findSecondDotPosition(String s) {
int result = -1;
int dotsToFind = 2;
char[] ca = s.toCharArray();
for (int i = 0; i < ca.length; ++i) {
if (ca[i] == '.') --dotsToFind;
if (dotsToFind == 0) return i;
}
return result;
}
}
The problem with split for beginner is, that is accepts regexp, that's why it is escaped in Joop Eggen's answe like this str.split("\\.").
And yes, that can be achieved in one line as user3458271 wrote in a comment same as xyz later in answer, just error checking would be more difficult (for example if there are no 2 dots...).
In one line with substring and indexOf:
String output = str.substring(0,str.indexOf(".",str.indexOf(".")+1));
public static void main(String[] args) {
String input = "2.111.1.190";
String[] out = input.split("\\.");
String output1 = out[0]+"."+out[1];
System.out.println(output1);
String output2 = "";
for(int x=2; x < out.length; x++)
output2 += out[x] +".";
System.out.println(output2);
}
For the other fields too:
String[] halfs = str.split("\\.");
String[] fulls = new String[halfs.length / 2];
for (int i = 0; i < fulls.length; ++i) {
fulls[i] = halfs[2*i] + "." + halfs[2*i + 1];
}
return fulls[0];
The same technique reduced for the first field:
String[] halfs = str.split("\\.", 3);
return halfs[0] + "." + halfs[1];
Simply:
return str.replaceAll("^([^.]*\\.[^.]*)\\..*$", "$1");
I'm building a simple program in Java that finds letters in strings and replaces them with a number, but I'm having trouble finding a method that will allow me to check for the exact specific character. There are plenty for digits and letters in general.
As my for loop stands now, it just replaces the letter everywhere, irregardless of whether it is within the range specified by start and end.
Any help would be appreciated.
String str = "A.A.A.A.A.A.A.A";
int start = 3;
int end = 9;
for (int i = start; i < end; i++) {
if (Character.isLetter(str.charAt(i)) {
str = str.replaceAll("A", "9");
return str;
Expected Output:
A.A.9.9.9.A.A.A
Actual Output:
9.9.9.9.9.9.9.9
In your code, you have
str = str.replaceAll("A", "9");
This will replace all the occurrences of A to 9
Instead of your approach, you should
1.Convert the string to a char array
char[] charArray = str.toCharArray();
2.Then replace each occurrence of character with a number
if (Character.isLetter(charArray[i])){
//Character Found
charArray[i] = '9';
}
3. Convert it back to string using
str = String.valueOf(charArray);
Modified Code:
String str = "A.A.A.A.A.A.A.A";
int start = 3;
int end = 9;
//Converting String to char array
char[] charArray = str.toCharArray();
for (int i = start; i < end; i++) {
if (Character.isLetter(charArray[i])){
//Character Found
charArray[i] = '9';
}
}
//Converting Back to String
str = String.valueOf(charArray);
System.out.println(charArray);
System.out.println(str);
Compare for character equality and then use string builder to replace the specified character
//Use of StringBuffer preferred over String as String are immutable
StringBuilder sb = new StringBuilder(str);
// -1 to start as index start from 0
for (int i = start-1; i < end; i++) {
char currentChar = currentString.charAt(i);
if (currentChar == "A") {
sb.setCharAt(i, '9');
}
}
return sb.toString();
I'd do it that way. Cut out the string to isolate the part you want to act on, do your replace ans stitch it all back together :
String str = "A.A.A.A.A.A.A.A";
int startIndex = 3;
int endIndex = 9;
String beginning = str.substring(0, startIndex);
String middle = str.substring(startIndex, endIndex);
String end = str.substring(endIndex);
middle = middle.replaceAll("A", "9");
String result = beginning + middle + end;
System.out.println(result);
Prints out :
A.A.9.9.9.A.A.A
EDIT:
As suggested in the comments, you could do it in one line
String str = "A.A.A.A.A.A.A.A";
int startIndex = 3;
int endIndex = 9;
String result =
str.substring(0, startIndex) +
str.substring(startIndex, endIndex).replaceAll("A", "9") +
str.substring(endIndex);
Here is an example using substrings to let you choose what portion of the string you want to test
int start = 3;
int end = 9;
String str = "A.A.A.A.A.A.A.A";
String startStr = str.substring(0,start);
String endStr = str.substring(end);
String newStr="";
char temp=' ';
for (int i = start; i < end; i++) {
temp = str.charAt(i);
if (temp=='A')
newStr+="9";
else
newStr += temp;
}
return(startStr + newStr + endStr);
You are replacing all the match found in the string and not specifying the index that needs to be replaced.
Use the StringBuffer replace method like below:
public static void main(String[] args) {
String str = "AAAAAAAA";
int start = 3;
int end = 9;
str = replaceBetweenIndexes(str, start, end, "9"); // AAA999AA
str = replaceBetweenIndexes("ABCD6EFG", start, end, "3"); // ABC363FG
}
public static String replaceBetweenIndexes(String str, int start, int end, String replaceWith) {
StringBuffer strBuf = new StringBuffer(str);
for (int i = start; i < end; i++) {
if (Character.isLetter(strBuf.charAt(i)) {
strBuf.replace(i, i+1, replaceWith);
}
}
return strBuf.toString();
}
This may sound like a very simple question but how do you remove multiple different characters from a string without having to write a line for each, which is what I have laboriously done. I have written a string example below:
String word = "Hello, t-his is; an- (example) line."
word = word.replace(",", "");
word = word.replace(".", "");
word = word.replace(";", "");
word = word.replace("-", "");
word = word.replace("(", "");
word = word.replace(")", "");
System.out.println(word);
Which would produce "Hello this is an example line". A more efficient way is?
Use
word = word.replaceAll("[,.;\\-()]", "");
Note that special character - (hyphen) should be escaped by double backslashes, because otherwise it is considered to construct a range.
Although no more efficient than the original replace technique you could use
word = word.replaceAll("\\p{Punct}+", "");
to use a simple expression using replaceAll with a wider range of characters replaced
Without (ab)using regex, I would do that way:
String word = "Hello, t-his is; an- (example) line.";
String undesirable = ",.;-()";
int len1 = undesirable.length();
int len2 = word.length();
StringBuilder sb = new StringBuilder(len2);
outer: for (int j = 0; j < len2; j++) {
char c = word.charAt(j);
for (int i = 0; i < len; i++) {
if (c == undesirable.charAt(i)) continue outer;
}
sb.append(c);
}
System.out.println(sb.toString());
The advantage is performance. You don't need the overhead of creating and parsing a regular expression.
You could encapsulate that in a method:
public static String removeCharacters(String word, String undesirable) {
int len1 = undesirable.length();
int len2 = word.length();
StringBuilder sb = new StringBuilder(len2);
outer: for (int j = 0; j < len2; j++) {
char c = word.charAt(j);
for (int i = 0; i < len1; i++) {
if (c == undesirable.charAt(i)) continue outer;
}
sb.append(c);
}
return sb.toString();
}
public static String removeSpecialCharacters(String word) {
return removeCharacters(word, ",.;-()");
}
And then, you would use it this way:
public static void testMethod() {
String word = "Hello, t-his is; an- (example) line.";
System.out.println(removeSpecialCharacters(word));
}
Here is a performance test:
public class WordTest {
public static void main(String[] args) {
int iterations = 10000000;
long t1 = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
testAsArray();
}
long t2 = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
testRegex();
}
long t3 = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
testAsString();
}
long t4 = System.currentTimeMillis();
System.out.println("Without regex, but using copied arrays: " + (t2 - t1));
System.out.println("With precompiled regex: " + (t3 - t2));
System.out.println("Without regex, but using string: " + (t4 - t3));
}
public static void testAsArray() {
String word = "Hello, t-his is; an- (example) line.";
char[] undesirable = ",.;-()".toCharArray();
StringBuilder sb = new StringBuilder(word.length());
outer: for (char c : word.toCharArray()) {
for (char h : undesirable) {
if (c == h) continue outer;
}
sb.append(c);
}
sb.toString();
}
public static void testAsString() {
String word = "Hello, t-his is; an- (example) line.";
String undesirable = ",.;-()";
int len1 = undesirable.length();
int len2 = word.length();
StringBuilder sb = new StringBuilder(len2);
outer: for (int j = 0; j < len2; j++) {
char c = word.charAt(j);
for (int i = 0; i < len1; i++) {
if (c == undesirable.charAt(i)) continue outer;
}
sb.append(c);
}
sb.toString();
}
private static final Pattern regex = Pattern.compile("[,\\.;\\-\\(\\)]");
public static void testRegex() {
String word = "Hello, t-his is; an- (example) line.";
String result = regex.matcher(word).replaceAll("");
}
}
The output on my machine:
Without regex, but using copied arrays: 5880
With precompiled regex: 11011
Without regex, but using string: 3844
Here is a solution to do this with minimal effort; the toRemove string contains all character you don't want to see in the output:
public static String removeChars(final String input, final String toRemove)
{
final StringBuilder sb = new StringBuilder(input.length());
final CharBuffer buf = CharBuffer.wrap(input);
char c;
while (buf.hasRemaining()) {
c = buf.get();
if (toRemove.indexOf(c) == -1)
sb.append(c);
}
return sb.toString();
}
If you use Java 8 you can even use this (unfortunately there's no CharStream so the casts are necessary...):
public static String removeChars(final String input, final String toRemove)
{
final StringBuilder sb = new StringBuilder(input.length());
input.chars().filter(c -> toRemove.indexOf((char) c) == -1)
.forEach(i -> sb.append((char) i));
return sb.toString();
}
You could try using a regular expression with Java's String.replaceAll method:
word = word.replaceAll(",|\.|;|-|\(|\)", "");
If you're not familiar with regular expressions, | means "or". So we are essentially saying , or . or ; or - or ( or ).
See more: Java documentation for String.replaceAll
Edit:
As mentioned, my previous version will not compile. Just for the sake of correctness (even though it has been pointed out that this is not the optimal solution), here is the corrected version of my regex:
word = word.replaceAll(",|\\.|;|-|\\(|\\)", "");
What I am trying to do, is create a method, that has a string and a character as parameters, the method then takes the string and searches for the given character. If the string contains that character, it returns an array of integers of where the character showed up. Here is what I have so far:
public class Sheet {
public static void main(String[] args) {
String string = "bbnnbb";
String complete = null;
//*******
for(int i = 0; i < string.length(); i++){
complete = StringSearch(string,'n').toString();
}
//********
}
public static int[] StringSearch(String string, char lookfor) {
int[]num = new int[string.length()];
for(int i = 0; i < num.length; i++){
if(string.charAt(i)== lookfor){
num[i] = i;
}
}
return num;
}
}
The method works fine, and returns this:
0
0
2
3
0
0
What I am trying to do, is make those into 1 string so it would look like this "002300".
Is there any possible way of doing this? I have tried to do it in the starred area of the code, but I have had no success.
just do
StringBuffer strBuff = new StringBuffer();
for(int i = 0; i<str.length(); i++)
{
if(str.charAt(i) == reqChar)
{
strBuff.append(str.charAt(i));
}
else
{
strBuff.append('0');
}
}
return str.toString();
Just add the result to the existing string with the += operator
String complete = "";
for(...)
complete += StringSearch(string,'n').toString();
I would just use java's regex library, that way it's more flexible (eg if you want to look for more than just a single character). Plus it's highly optimized.
StringBuilder positions = "";
Pattern pattern = Pattern.compile(string);
Matcher matcher = pattern.matcher(lookfor);
while(matcher.find()){
positions.append(matcher.start());
}
return positions;
Updated with StringBuilder for better practices.
public static String StringSearch(String string, char lookfor) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < string.length; i++){
if(string.charAt(i) == lookfor)
sb.append(i);
else
sb.append("0");
}
return sb.toString();
}
Then you can just call it once, without a for loop. Not sure why you call it for every character in the string.
complete = StringSearch(string,'n');