Finding second occurrence of a substring in a string in Java - java

We are given a string, say, "itiswhatitis" and a substring, say, "is".
I need to find the index of 'i' when the string "is" occurs a second time in the original string.
String.indexOf("is") will return 2 in this case. I want the output to be 10 in this case.

Use overloaded version of indexOf(), which takes the starting index (fromIndex) as 2nd parameter:
str.indexOf("is", str.indexOf("is") + 1);

I am using:
Apache Commons Lang: StringUtils.ordinalIndexOf()
StringUtils.ordinalIndexOf("Java Language", "a", 2)

int first = string.indexOf("is");
int second = string.indexOf("is", first + 1);
This overload starts looking for the substring from the given index.

You can write a function to return array of occurrence positions, Java has String.regionMatches function which is quite handy
public static ArrayList<Integer> occurrencesPos(String str, String substr) {
final boolean ignoreCase = true;
int substrLength = substr.length();
int strLength = str.length();
ArrayList<Integer> occurrenceArr = new ArrayList<Integer>();
for(int i = 0; i < strLength - substrLength + 1; i++) {
if(str.regionMatches(ignoreCase, i, substr, 0, substrLength)) {
occurrenceArr.add(i);
}
}
return occurrenceArr;
}

I hope I'm not late to the party.. Here is my answer. I like using Pattern/Matcher because it uses regex which should be more efficient. Yet, I think this answer could be enhanced:
Matcher matcher = Pattern.compile("is").matcher("I think there is a smarter solution, isn't there?");
int numOfOcurrences = 2;
for(int i = 0; i < numOfOcurrences; i++) matcher.find();
System.out.println("Index: " + matcher.start());

It seems to be a good party... I'm in:
public static int nthIndexOf(String str, String subStr, int count) {
int ind = -1;
while(count > 0) {
ind = str.indexOf(subStr, ind + 1);
if(ind == -1) return -1;
count--;
}
return ind;
}

i think a loop can be used.
1 - check if the last index of substring is not the end of the main string.
2 - take a new substring from the last index of the substring to the last index of the main string and check if it contains the search string
3 - repeat the steps in a loop

if you want to find index for more than 2 occurrence:
public static int ordinalIndexOf(String fullText,String subText,int pos){
if(fullText.contains(subText)){
if(pos <= 1){
return fullText.indexOf(subText);
}else{
--pos;
return fullText.indexOf(subText, ( ordinalIndexOf(fullText,subText,pos) + 1) );
}
}else{
return -1;
}
}

Anyone who is looking for Nth occurance of string
public class NthOccuranceExample {
public static void main(String[] args) {
String str1 = "helloworld good morning good evening good night";
String str2 = "ing";
int n = 2;
int index = nthOccurrence(str1, str2, n);
System.out.println("index of str2 in str1 at occurrence "+ n +" = "+ index);
}
public static int nthOccurrence(String str1, String str2, int n) {
String tempStr = str1;
int tempIndex = -1;
int finalIndex = 0;
for(int occurrence = 0; occurrence < n ; ++occurrence){
tempIndex = tempStr.indexOf(str2);
if(tempIndex==-1){
finalIndex = 0;
break;
}
tempStr = tempStr.substring(++tempIndex);
finalIndex+=tempIndex;
}
return --finalIndex;
}
}

Related

Count Words Using indexOf

I can't use arrays, only simple Java (if, for, while, substring, length, indexOf)
public int howManyWords(String s){
myString = "I have a dream";
int count = 1;
int length = 0;
while(count>=0){
count = myString.substring(String.valueOf(length),myString.indexOf(" "));
count++;
length = myString.indexOf(" ");
}
return count;
}
Should return 4
First of all, you made infinite loop, because count is 1, and you just increase it.
Second, you haven't even try to write this code in some IDE, because it would throw you a syntax error, because you are assigning string to int, when you do count = myString.substring()
So, instead of using count in loop, you can use myString.indexOf
something like this could work if you don't care what is going to happen with myString
int count = 0;
while(myString.indexOf(" ") >= 0) {
count++;
myString = myString.substring(myString.indexOf(" ") + 1)
}
return count;
Let's assume that the string you are testing does not contain leading or trailing spaces, because that affects the solution. The example string in your question does not contain leading or trailing spaces.
Simply call method indexOf(String, int) in a loop and in each iteration you set the int parameter to one more than what you got in the previous iteration. Once the value returned by method indexOf() is -1 (minus one), you are done. But don't forget to add the last word after you exit the loop.
String myString = "I have a dream";
int count = 0;
int index = 0;
while (index >= 0 && index < myString.length()) {
index = myString.indexOf(" ", index);
System.out.println("index = " + index);
if (index >= 0) {
index++;
count++;
}
}
if (index < 0) {
count++;
}
System.out.println("count = " + count);
Edited : Added missing else case.
Try the following code :
Remove the counted words from your string using the substring and indexOf, and increment the count in each iteration.
public int countWords(String s){
String myString = "I have a dream";
int count = 0;
int length = myString.length();
while(length>0){
if((myString.indexOf(" ")!=-1) && (myString.indexOf(" ")+1)<length){
myString = myString.subString(myString.indexOf(" ")+1);
count++;
length = myString.length();
}
else {
length = 0;
break;
}
}
return count;
}
PS: Conventionally, your method names should denote actions, hence I suggested it to be countWords instead of howManyWords.

How to return string with all instances of a string replaced by another string ( Java )

In this program, I am trying to return a new string that is composed of new letters that were added and old letters if the didn't fit the constraints. I am stuck in terms of I don't know how to fix my code so that it prints correctly. Any help or suggestions is greatly appreciated!
Here are some examples:
str: "asdfdsdfjsdf", word: "sdf", c: "q"
should return "aqdqjq", I'm getting "asdqqq"
str: "aaaaaaaa", word: "aaa", c: "w"
should return "wwaa", as of right now my code only returns "ww"
public static String replaceWordWithLetter(String str, String word, String c)
String result = "";
int index = 0;
while (index < str.length() )
{
String x = str.substring(index, index + word.length() );
if (x.equals(word))
{
x = c;
index = index + word.length();
}
result = result + x;
index++;
}
if (str.length() > index)
{
result = result + str.substring(index, str.length() - index);
}
return result;
}
You seem to be overcomplicating this. You can simply use the replace() method:
public static String replaceWordWithLetter(String str, String word, String c) {
return str.replace(word, c);
}
Which when called as:
replaceWordWithLetter("asdfdsdfjsdf", "sdf", "q")
Produces the output:
aqdqjq
The problem with your current method is that if the substring is not equal to word, then you will append as many characters as there are in word, and then only move up one index. If you will not be replacing the sequence, then you only need to append one character to result. Also it is much more efficient to use a StringBuilder. Also as noted if the String is not divisible by word.length(), this will throw a StringIndexOutOfBoundsError. To solve this you can use the Math.min() method to ensure that the substring does not go out of bounds. Original method with fixes:
public static String replaceWordWithLetter(String str, String word, String c) {
StringBuilder result = new StringBuilder();
int index = 0;
while (index < str.length() )
{
String x = str.substring(index, Math.min(index + word.length(), str.length()));
if (x.equals(word))
{
result.append(c);
index = index + word.length();
}
//If we aren't replacing, only add one char
else {
result.append(x.charAt(0));
index++;
}
}
if (str.length() > index)
{
result.append(str.substring(index, str.length() - index));
}
return result.toString();
}
Found the fix to my issue using #GBlodgett's code:
String result = "";
int index = 0;
while (index <= str.length() - word.length() )
{
String x = str.substring(index, index + word.length() );
if (x.equals(word))
{
result = result + c;
index = index + word.length();
}
else {
result = result + x.charAt(0);
index++;
}
}
if (str.length() < index + word.length())
{
result = result + (str.substring(index));
}
return result;
}
You can use String.replaceAll() method.
example:
public class StringReplace {
public static void main(String[] args) {
String str = "aaaaaaaa";
String fnd = "aaa";
String rep = "w";
System.out.println(str.replaceAll(fnd, rep));
System.out.println("asdfdsdfjsdf".replaceAll("sdf", "q"));
}
}
Output:
wwaa
aqdqjq

Counting Letters Between the First and Last - Java

OK, so I'm doing this project that requires that I have the first and last setters of a string appear with the number of letters in between them counted, and output. I've tried repurposing some reverse a string code I had handy, but I cannot get the output to appear in my IDE.
Can anyone look over my code, and make some suggestions?
public static void main(String[] args) {
String countWord;
countWord = JOptionPane.showInputDialog(null,
"Enter the string you wish to have formatted:");
}
static String countMe(String countWord) {
int count = 1;
char first = countWord.charAt (0);
char last = countWord.charAt(-1);
StringBuilder word = new StringBuilder();
for(int i = countWord.length() - 1; i >= 0; --i)
if (countWord.charAt(i) != first ) {
if (countWord.charAt(i) != last) {
count++;
}
}
return countWord + first + count + last;
}
}
Just build it using charAt():
return "" + str.charAt(0) + (str.length() - 2) + str.charAt(str.length() - 1);
The "" at the front causes the numeric values that follow to be concatenated as Strings (instead of added arithmetically).
A slightly more terse alternative is:
return countWord.replaceAll("(.).*(.)", "$1" + (str.length() - 2) + "$2")
Once you determined the first and last chars, it is no need for unnecessary conditions. Just try this:
static String countMe(String countWord) {
char first = countWord.charAt(0);
char last = countWord.charAt(countWord.length()-1);
int count=0;
for (int i = 1; i < countWord.length()-1; i++)
{
count++;
}
return first + String.valueOf(count) + last;
}
Or, if it is not mandatory to use for loop, you can make it simple as this
static String countMe(String countWord) {
char first = countWord.charAt(0);
char last = countWord.charAt(countWord.length()-1);
int count = countWord.substring(1, countWord.length()-1).length();
return first + String.valueOf(count) + last;
}
You could use the string.length() method to obtain the total length of the string. Your code would be something like:
int totalLength = countWord.length();
int betweenLength = totalLength - 2; // This gives the count of characters between first and last letters
char first = countWord.charAt(0);
char last = countWord.charAt(str.length() - 1);
String answer = first + betweenLength + last;
import javax.swing.JOptionPane;
public class Main{
public static void main(String[] args) {
String countWord;
countWord = JOptionPane.showInputDialog(null,
"Enter the word you wish to have formatted:");
JOptionPane.showMessageDialog(null, countMe(countWord));
}
static String countMe(String countWord) {
int count = 0;
String first = String.valueOf(countWord.charAt(0));
String last = String.valueOf(countWord.charAt(countWord.length() - 1));
for(int i = 1; i < countWord.length() - 1; i++) {
if (String.valueOf(countWord.charAt(i)) != first ) {
count++;
}
}
return first + count + last;
}
}

Java function for counting word

Is there any default method in Java that can count total occurrence of a word? For example, how many times stack occurred in a string "stack is stack".
Edit: please only Java no third party library.
You can use StringUtils.countMatches(string, "stack") from commons-lang. This doesn't account for word boundaries, so "stackstack" will be counted as two occurences.
There is no built-in .matchCount() method. Here is my impl.
public static int matchCount(String s, String find) {
String[] split = s.split(" ");
int count = 0;
for(int i=0; i<split.length; i++){
if(split[i].equals(find)){
count++;
}
}
return count;
}
String s = "stack is stack";
System.out.println(matchCount(s, "stack")); // 2
You could use:
public static int NumTimesInString(String target, String regex)
{
return (" " + target + " ").split(regex).length - 1;
}
This will work so long as regex doesn't match a beginning or ending space... Hmm, this might not work for some cases. You might be better writing a function which uses indexOf
public static int NumTimesInString(String target, String substr)
{
int index = 0;
int count = -1;
while (index != -1)
{
index = target.indexOf(substr, index);
count++;
}
return count;
}
NOTE: not tested
Either one can be used as:
int count = NumTimesInString("hello world hello foo bar hello", "hello");
// count is 3

how to split a string by position in Java

I did not find anywhere an answer.. If i have: String s = "How are you"?
How can i split this into two strings, so first string containing from 0..s.length()/2 and the 2nd string from s.length()/2+1..s.length()?
Thanks!
This should do:
String s = "How are you?";
String first = s.substring(0, s.length() / 2); // gives "How ar"
String second = s.substring(s.length() / 2); // gives "e you?"
String.substring(int i) with one argument returns the substring beginning at position i
String.substring(int i, int j) with two arguments returns the substring beginning at i and ending at j-1.
(Note that if the length of the string is odd, second will have one more character than first due to the rounding in the integer division.)
String s0 = "How are you?";
String s1 = s0.subString(0, s0.length() / 2);
String s2 = s0.subString(s0.length() / 2);
So long as s0 is not null.
EDIT
This will work for odd length strings as you are not adding 1 to either index. Surprisingly it even works on a zero length string "".
You can use 'substring(start, end)', but of course check if string isn't null before:
String first = s.substring(0, s.length() / 2);
String second = s.substring(s.length() / 2);
http://www.roseindia.net/java/beginners/SubstringExample.shtml
And are you expecting string with odd length ? in this case you must add logic to handle this case correctly.
Here's a method that splits a string into n items by length. (If the string length can not exactly be divided by n, the last item will be shorter.)
public static String[] splitInEqualParts(final String s, final int n){
if(s == null){
return null;
}
final int strlen = s.length();
if(strlen < n){
// this could be handled differently
throw new IllegalArgumentException("String too short");
}
final String[] arr = new String[n];
final int tokensize = strlen / n + (strlen % n == 0 ? 0 : 1);
for(int i = 0; i < n; i++){
arr[i] =
s.substring(i * tokensize,
Math.min((i + 1) * tokensize, strlen));
}
return arr;
}
Test code:
/**
* Didn't use Arrays.toString() because I wanted to have quotes.
*/
private static void printArray(final String[] arr){
System.out.print("[");
boolean first = true;
for(final String item : arr){
if(first) first = false;
else System.out.print(", ");
System.out.print("'" + item + "'");
}
System.out.println("]");
}
public static void main(final String[] args){
printArray(splitInEqualParts("Hound dog", 2));
printArray(splitInEqualParts("Love me tender", 3));
printArray(splitInEqualParts("Jailhouse Rock", 4));
}
Output:
['Hound', ' dog']
['Love ', 'me te', 'nder']
['Jail', 'hous', 'e Ro', 'ck']
Use String.substring(int), and String.substring(int, int) method.
int cutPos = s.length()/2;
String s1 = s.substring(0, cutPos);
String s2 = s.substring(cutPos, s.length()); //which is essentially the same as
//String s2 = s.substring(cutPos);
I did not find anywhere an answer.
The first place you should always look is at the javadocs for the class in question: in this case java.lang.String. The javadocs
can be browsed online on the Oracle website (e.g. at http://download.oracle.com/javase/6/docs/api/),
are included in any Sun/Oracle Java SDK distribution,
are probably viewable in your Java IDE, and
and be found using a Google search.
public int solution(final String S, final int K) {
int splitCount = -1;
final int count = (int) Stream.of(S.split(" ")).filter(v -> v.length() > K).count();
if (count > 0) {
return splitCount;
}
final List<String> words = Stream.of(S.split(" ")).collect(Collectors.toList());
final List<String> subStrings = new ArrayList<>();
int counter = 0;
for (final String word : words) {
final StringJoiner sj = new StringJoiner(" ");
if (subStrings.size() > 0) {
final String oldString = subStrings.get(counter);
if (oldString.length() + word.length() <= K - 1) {
subStrings.set(counter, sj.add(oldString).add(word).toString());
} else {
counter++;
subStrings.add(counter, sj.add(word).toString());
}
} else {
subStrings.add(sj.add(word).toString());
}
}
subStrings.forEach(
v -> {
System.out.printf("[%s] and length %d\n", v, v.length());
}
);
splitCount = subStrings.size();
return splitCount;
}
public static void main(final String[] args) {
final MessageSolution messageSolution = new MessageSolution();
final String message = "SMSas5 ABC DECF HIJK1566 SMS POP SUV XMXS MSMS";
final int maxSize = 11;
System.out.println(messageSolution.solution(message, maxSize));
}

Categories