Ebrin
Ebrin

Reputation: 209

Count the number of Strings in a String

I'm trying to count the number of symbol (String) occurrences within a text (String). I've seen some other solutions here, but they're more advanced or use libraries. My idea is to reduce the string at each occurrence of the symbol. I use .indexOf(symbol,1) to search for symbol from index 1 because if it searches at 0 it just stops. However, the code overcounts by one most of the time.

String text = readLine("Enter text");
String symbol = readLine("Enter symbol");

int count = 0;
while (true) {
    if (!text.contains(symbol)) {
        break;
    }
    count++;
    if ((text.indexOf(symbol, 1)) == -1) {
        break;
    }
    text = text.substring(text.indexOf(symbol, 1));
    System.out.println(text);
    System.out.println(count);
}

System.out.println("Symbol " + symbol + " appears in text " + count + " times.");

Please help me find the flaw in logic, and also tell me if this approach is good or bad.

Upvotes: 0

Views: 2551

Answers (4)

Unmitigated
Unmitigated

Reputation: 89527

An alternative to using substring is to keep track of the previous index the string was found at and use String#indexOf(str, fromIndex).

int count = 0;
for(int idx = -1; (idx = text.indexOf(symbol, idx + 1)) != -1; count++);
System.out.println("Symbol " + symbol + " appears in text " + count + " times.");

Upvotes: 0

meriton
meriton

Reputation: 70584

Since tibetiroka has already identified the flaw in your code, I'll only tackle the second part of your question:

also tell me if this approach is good or bad.

It works, but it is both quite complicated and not very efficient at runtime. The reason is that substring() copies all remaining characters into a new string. For instance, suppose your text contains the symbol 1000 times, and nothing else. Then, after finding the first symbol, your code will copy the 999 remaining symbols, and 998 after finding the second symbol, and so on, for a total of about 500 000 symbol copies, even though there are only 1000 symbols in the text!

It is therefore better to avoid substring(), and instead use the second parameter to indexOf() to resume looking after the last symbol found:

int count = 0;
int index = 0;
while (true) {
    index = text.indexOf(symbol, index); // find next occurrence of symbol
    if (index == -1) {
      return count;
    }
    count++;
    index++;
}

I've also eliminated the use of contains(), since indexOf() already tells us if there is another occurrence.

One last thing: You didn't specify whether overlapping symbols should be counted. For instance, if we look for "aba" in the text "ababa", is that one or two occurrences? If occurrences shouldn't overlap, we can achieve this by saying index += symbol.length whenever we find a symbol.

Upvotes: 1

Maurice
Maurice

Reputation: 357

I think you can try the following:

String text = readLine("Enter text");
char symbol = readLine("Enter symbol").charAt(0);

int count = 0;
for(char character: text.toCharArray()) {
    if(symbol == character) {
        count++;
    }
}
System.out.println("Count: " + count);

This just loops through each character of the string and compares it to the entered symbol

Upvotes: 0

user10992464
user10992464

Reputation:

if (!text.contains(symbol)) {
    break;
}
count++;
if ((text.indexOf(symbol, 1)) == -1) {
    break;
}

This part of your code is quite problematic. You increment the count if the symbol is present in the text, even if it is the first character - while your

text = text.substring(text.indexOf(symbol, 1));

code assures that the first character is the specified symbol in the text. This causes your code to overcount by one if it contains the specified symbol. To fix it, change your code to

while (true) {
    if (!text.contains(symbol)) {
        break;
    }
    count++;
    text = text.substring(text.indexOf(symbol)+1);//+1 so it starts at the next character
    System.out.println(text);
    System.out.println(count);
}

As you can see, the first character is no longer the specified symbol. This ensures that

  1. The contains() method is enough to determine the presence of the symbol
  2. The count is set correctly

Upvotes: 1

Related Questions