Related
Edit: To those who downvote me, this question is difference from the duplicate question which you guy linked. The other question is about returning the indexes. However, for my case, I do not need the index. I just want to check whether there is duplicate.
This is my code:
String word = "ABCDE<br>XYZABC";
String[] keywords = word.split("<br>");
for (int index = 0; index < keywords.length; index++) {
if (keywords[index].toLowerCase().contains(word.toLowerCase())) {
if (index != (keywords.length - 1)) {
endText = keywords[index];
definition.setText(endText);
}
}
My problem is, if the keywords is "ABC", then the string endText will only show "ABCDE". However, "XYZABC" contains "ABC" as well. How to check if the string has multiple occurrence? I would like to make the definition textview become definition.setText(endText + "More"); if there is multiple occurrence.
I tried this. The code is working, but it is making my app very slow. I guess the reason is because I got the String word through textwatcher.
String[] keywords = word.split("<br>");
for (int index = 0; index < keywords.length; index++) {
if (keywords[index].toLowerCase().contains(word.toLowerCase())) {
if (index != (keywords.length - 1)) {
int i = 0;
Pattern p = Pattern.compile(search.toLowerCase());
Matcher m = p.matcher( word.toLowerCase() );
while (m.find()) {
i++;
}
if (i > 1) {
endText = keywords[index];
definition.setText(endText + " More");
} else {
endText = keywords[index];
definition.setText(endText);
}
}
}
}
Is there any faster way?
It's a little hard for me to understand your question, but it sounds like:
You have some string (e.g. "ABCDE<br>XYZABC"). You also have some target text (e.g. "ABC"). You want to split that string on a delimiter (e.g. "<br>", and then:
If exactly one substring contains the target, display that substring.
If more than one substring contains the target, display the last substring that contains it plus the suffix "More"
In your posted code, the performance is really slow because of the Pattern.compile() call. Re-compiling the Pattern on every loop iteration is very costly. Luckily, there's no need for regular expressions here, so you can avoid that problem entirely.
String search = "ABC".toLowerCase();
String word = "ABCDE<br>XYZABC";
String[] keywords = word.split("<br>");
int count = 0;
for (String keyword : keywords) {
if (keyword.toLowerCase().contains(search)) {
++count;
endText = keyword;
}
}
if (count > 1) {
definition.setText(endText + " More");
}
else if (count == 1) {
definition.setText(endText);
}
You are doing it correctly but you are doing unnecessary check which is if (index != (keywords.length - 1)). This will ignore if there is match in the last keywords array element. Not sure is that a part of your requirement.
To enhance performance when you found the match in second place break the loop. You don't need to check anymore.
public static void main(String[] args) {
String word = "ABCDE<br>XYZABC";
String pattern = "ABC";
String[] keywords = word.split("<br>");
String endText = "";
int count = 0;
for (int index = 0; index < keywords.length; index++) {
if (keywords[index].toLowerCase().contains(pattern.toLowerCase())) {
//If you come into this part mean found a match.
if(count == 1) {
// When you found the second match it will break to loop. No need to check anymore
// keep the first found String and append the more part to it
endText += " more";
break;
}
endText = keywords[index];
count++;
}
}
System.out.println(endText);
}
This will print ABCDE more
Hi You have to use your condition statement like this
if (word.toLowerCase().contains(keywords[index].toLowerCase()))
You can use this:
String word = "ABCDE<br>XYZABC";
String[] keywords = word.split("<br>");
for (int i = 0; i < keywords.length - 1; i++) {
int c = 0;
Pattern p = Pattern.compile(keywords[i].toLowerCase());
Matcher m = p.matcher(word.toLowerCase());
while (m.find()) {
c++;
}
if (c > 1) {
definition.setText(keywords[i] + " More");
} else {
definition.setText(keywords[i]);
}
}
But like what I mentioned in comment, there is no double occurrence in word "ABCDE<br>XYZABC" when you want to split it by <br>.
But if you use the word "ABCDE<br>XYZABCDE" there is two occurrence of word "ABCDE"
void test() {
String word = "ABCDE<br>XYZABC";
String sequence = "ABC";
if(word.replaceFirst(sequence,"{---}").contains(sequence)){
int startIndex = word.indexOf(sequence);
int endIndex = word.indexOf("<br>");
Log.v("test",word.substring(startIndex,endIndex)+" More");
}
else{
//your code
}
}
Try this
I want to divide the following message by 10 character. I want to append every part into StringBuilder object.
04421,1,13,S,312|4000004130,1;4000000491,1;4000005240,1;4000005789,2;4000004978,2;4000004934,2;4000004936,1;4000000569,2;4000005400,1;4000000;4000004934,2;
I have done the following solution :
if(getMsgOtherPart(message) != null){
System.out.println("part message::"+getMsgOtherPart(message));
String newMessage = getMsgOtherPart(message) ;
int len = newMessage.length();
System.out.println("len::"+len);
int firstIndex = 0;
int limit = 10;
int lastIndex = 10;
int count = 0;
StringBuilder sb = new StringBuilder();
String completeMessage = null;
for(int i = 0; i <= len;i++){
count++;
if( count == limit && lastIndex < len){
sb.append(getSmsUniqueHeader());
sb.append(newMessage.substring(firstIndex,lastIndex));
sb.append("#");
sb.append("\n");
firstIndex = lastIndex;
lastIndex = firstIndex + limit;
count = 0;
} else if(count < limit && i == len) {
System.out.println("lastIndex:: "+lastIndex);
sb.append(getSmsUniqueHeader());
sb.append(newMessage.substring(lastIndex-10));
sb.append("#");
}
}
completeMessage = sb.toString();
System.out.println("message::\n"+completeMessage);
}
I am getting output:
message::
$04421,1,13#
$,S,312|400#
$0004130,1;#
$4000000491#
$;400000540#
$0,1;400000#
$0;40000000#
$63,1;40000#
$00076,1;40#
$00000776,2#
$;400000078#
$8,2;400000#
------------
$0;#
Please let me know to optimize my solution.
I had done this kind of thing in one of my project and here is the function i used, which return the List but you can modify it and use StringBuilder.
public List<String> splitStringEqually(String txtStr, int subStringSize) {
List<String> splittedStringList = new ArrayList<String>();
for (int start = 0; start < txtStr.length(); start += subStringSize) {
splittedStringList.add(txtStr.substring(start, Math.min(txtStr.length(), start + subStringSize)));
}
return splittedStringList;
}
You can use Google's Guava library and use the Splitter class for this.
StringBuilder sb=new StringBuilder();
for(String s: Splitter.fixedLength(10).split(message)){
sb.append(s);
sb.append("#\n");
}
System.out.println(sb.toString());
String is maintained as char array internally. You can get the copy of that char array using message.toCharArray() and using a simple loop or java 8 streams pick elements in chunks of 10 and do whatever stuff you need to do.
Basing heavily on Rajen Raiyarela's answer and addressing the specific request from the OP, the code may look like this (upvote that one, not this one please!):
public String splitStringEqually(String txtStr, int subStringSize) {
// Start off with the header
StringBuilder sb = new StringBuilder("message::\n");
int len = txtStr.length();
for (int start = 0; start < len; start += subStringSize) {
sb.append("$");
// Copy the next 10 characters, or less if at end of string
// Does not use txtStr.substring() as that creates an
// unnecessary temporary string
sb.append(txtStr, start, Math.min(len, start + subStringSize));
sb.append("#\n");
}
return sb.toString();
}
This can be called with simply:
String completeMessage = splitStringEqually(newMessage, limit);
I'm trying to get an int from a String. The String will always come as:
"mombojumbomombojumbomombojumbomombojumbomombojumbomombojumbohello=1?fdjaslkd;fdsjaflkdjfdklsa;fjdklsa;djsfklsa;dfjklds;afj=124214fdsamf=352"
The only constant in all of this, is that I will have a "hello=" followed by a number. With just that, I can't figure out how to pull out the number after the "hello=". This is what I have tried so far with no luck.
EDIT: The number will always be followed by a "?"
String[] tokens = s.split("hello=");
for (String t : tokens)
System.out.println(t);
I can't figure out how to isolate it from both sides of the int.
Pattern p = Pattern.compile("hello=(\\d+)");
Matcher m = p.matcher (s);
while (m.find())
System.out.println(m.group(1));
This sets up a search for anywhere in s that contains hello= followed by one or more digits (\\d+ means one or more digits). The loop looks for each occurrence of this pattern, and then whenever it finds a match, m.group(1) extracts the digits (since those are grouped in the pattern).
You should use a regular expression for this:
String str = "mombojumbomombojumbomombojumbomombojumbomombojumbomombojumbohello=1fdjaslkd;fdsjaflkdjfdklsa;fjdklsa;djsfklsa;dfjklds;afj=124214fdsamf=352";
Pattern p = Pattern.compile("hello=(\\d+)");
Matcher m = p.matcher(str);
if (m.find()) {
System.out.println(m.group(1)); // prints 1
}
Try this:
String r = null;
int col = s.indexOf("hello="); // find the starting column of the marker string
if (col >= 0) {
String s2 = s.substring(col + 6); // get digits and the rest (add length of marker)
col = 0;
// now find the end of the digits (assume no plus or comma or dot chars)
while (col < s2.length() && Character.isDigit(s2.charAt(col))) {
col++;
}
if (col > 0) {
r = s2.substring(0, col); // get the digits off the front
}
}
r will be the string you want or it will be null if no number was found.
Here is another non-regex performance approach. Wrapped in a method for your convenience
Helper method
public static Integer getIntegerForKey(String key, String s)
{
int startIndex = s.indexOf(key);
if (startIndex == -1)
return null;
startIndex += key.length();
int endIndex = startIndex;
int len = s.length();
while(endIndex < len && Character.isDigit(s.charAt(endIndex))) {
++endIndex;
}
if (endIndex > startIndex)
return new Integer(s.substring(startIndex, endIndex));
return null;
}
Usage
Integer result = getIntegerForKey("hello=", yourInputString);
if (result != null)
System.out.println(result);
else
System.out.println("Key-integer pair not found.");
Yet another non regex solution:
String str = "mombojumbomombojumbomombojumbomombojumbomombojumbomombojumbohello=142?fdjaslkd;fdsjaflkdjfdklsa;fjdklsa;djsfklsa;dfjklds;afj=124214fdsamf=352";
char arr[] = str.substring(str.indexOf("hello=")+6).toCharArray();
String buff ="";
int i=0;
while(Character.isDigit(arr[i])){
buff += arr[i++];
}
int result = Integer.parseInt(buff);
System.out.println(result);
I have to String objects:
String first = "/Some object that has a loop in it object/";
String second = "object";
What I need to do is find how many times does the second object repeat in the first object, can you please show me how to do that?
Use this single line which utilizes regular expressions in the background:
String[] parts = first.split(second);
String second occurs (parts.length - 1) times in String first. That's all.
EDIT:
To prevent unwanted results that could occur in the case of String second might contain regex-specific characters, you can use Pattern.quote(second) when passing it to split() method, as one of the commentators suggested.
The simplest way is to use indexOf in a loop, advancing the starting index each time that you find the word:
int ind = 0;
int cnt = 0;
while (true) {
int pos = first.indexOf(second, ind);
if (pos < 0) break;
cnt++;
ind = pos + 1; // Advance by second.length() to avoid self repetitions
}
System.out.println(cnt);
This will find the word multiple times if a word contains self-repetitions. See the comment above to avoid such "duplicate" finds.
Demo on ideone.
Use regex, example:
import java.util.regex.*;
class Test {
public static void main(String[] args) {
String hello = "HelloxxxHelloxxxHello"; //String you want to 'examine'
Pattern pattern = Pattern.compile("Hello"); //Pattern string you want to be matched
Matcher matcher = pattern.matcher(hello);
int count = 0;
while (matcher.find())
count++; //count any matched pattern
System.out.println(count); // prints how many pattern matched
}
}
source: java regex match count
try like below...
String str = "/Some object that has a loop in it object/";
String findStr = "object";
int lastIndex = 0;
int count =0;
while(lastIndex != -1){
lastIndex = str.indexOf(findStr,lastIndex);
if( lastIndex != -1){
count ++;
lastIndex+=findStr.length();
}
}
System.out.println(count);
You can either split the String on the second String and count the length of the resulting array, it will have one more element that that number of occurrences. Or you can use Pattern and Matcher, which is a slightly more proper approach.
public static void main(String[] args) throws UnsupportedEncodingException, IOException {
String first = "/Some object that has a loop in it object/";
String second = "object";
System.out.println(first.split(Pattern.quote(second)).length - 1);
final Pattern pattern = Pattern.compile(Pattern.quote(second));
final Matcher matcher = pattern.matcher(first);
int count = 0;
while (matcher.find()) {
count++;
}
System.out.println(count);
}
Don't forget to use Pattern.quote just in case.
Use this :
String first = "/Some object that has a loop in it object/";
String second = "object";
Pattern pattern = Pattern.compile(second);
Matcher matcher = pattern.matcher(first) ;
long count = 0;
while(matcher.find()) {
count ++;
}
System.out.println(count);
I know this is an older topic, but off the top of my head, you could use recursion:
// Recursive routine to find the xth repeat of a string
public int atIndex(String searchin, String searchfor, int whichone, int pos) {
return atIndex(searchin, searchfor, whichone, pos, 0);
}
public int atIndex(String searchin, String searchfor, int whichone, int pos, int recursed) {
return (whichone>0?atIndex(searchin, searchfor, --whichone, searchin.indexOf(searchfor,pos)+1,++recursed):(recursed==0?-1:pos-1));
}
I'm new at Java, so there may be a speed or resources issue that I'm not aware of, but a little bit of testing should suss out any problems.
To call it, you might use:
String HL7Test="MSH|^~\\&|EPIC|EPICADT|SMS|SMSADT|199912271408|CHARRIS|ADT^A04|1817457" ;
System.out.println(atIndex(HL7Test, "|", 4, 0));
Hope this helps.
Here you only need two variables and do all the checking in the loop condition.
int pos = 0;
int count= 0;
while (first.indexOf(second, pos) >= 0) {
count++;
pos = first.indexOf(second, pos) + 1;
}
System.out.println(count);
Why is the following algorithm not halting for me?
In the code below, str is the string I am searching in, and findStr is the string occurrences of which I'm trying to find.
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;
while (lastIndex != -1) {
lastIndex = str.indexOf(findStr,lastIndex);
if( lastIndex != -1)
count++;
lastIndex += findStr.length();
}
System.out.println(count);
How about using StringUtils.countMatches from Apache Commons Lang?
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
System.out.println(StringUtils.countMatches(str, findStr));
That outputs:
3
Your lastIndex += findStr.length(); was placed outside the brackets, causing an infinite loop (when no occurence was found, lastIndex was always to findStr.length()).
Here is the fixed version :
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;
while (lastIndex != -1) {
lastIndex = str.indexOf(findStr, lastIndex);
if (lastIndex != -1) {
count++;
lastIndex += findStr.length();
}
}
System.out.println(count);
A shorter version. ;)
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
System.out.println(str.split(findStr, -1).length-1);
The last line was creating a problem. lastIndex would never be at -1, so there would be an infinite loop. This can be fixed by moving the last line of code into the if block.
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;
while(lastIndex != -1){
lastIndex = str.indexOf(findStr,lastIndex);
if(lastIndex != -1){
count ++;
lastIndex += findStr.length();
}
}
System.out.println(count);
Do you really have to handle the matching yourself ? Especially if all you need is the number of occurences, regular expressions are tidier :
String str = "helloslkhellodjladfjhello";
Pattern p = Pattern.compile("hello");
Matcher m = p.matcher(str);
int count = 0;
while (m.find()){
count +=1;
}
System.out.println(count);
I'm very surprised no one has mentioned this one liner. It's simple, concise and performs slightly better than str.split(target, -1).length-1
public static int count(String str, String target) {
return (str.length() - str.replace(target, "").length()) / target.length();
}
Here it is, wrapped up in a nice and reusable method:
public static int count(String text, String find) {
int index = 0, count = 0, length = find.length();
while( (index = text.indexOf(find, index)) != -1 ) {
index += length; count++;
}
return count;
}
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;
while((lastIndex = str.indexOf(findStr, lastIndex)) != -1) {
count++;
lastIndex += findStr.length() - 1;
}
System.out.println(count);
at the end of the loop count is 3; hope it helps
public int countOfOccurrences(String str, String subStr) {
return (str.length() - str.replaceAll(Pattern.quote(subStr), "").length()) / subStr.length();
}
A lot of the given answers fail on one or more of:
Patterns of arbitrary length
Overlapping matches (such as counting "232" in "23232" or "aa" in "aaa")
Regular expression meta-characters
Here's what I wrote:
static int countMatches(Pattern pattern, String string)
{
Matcher matcher = pattern.matcher(string);
int count = 0;
int pos = 0;
while (matcher.find(pos))
{
count++;
pos = matcher.start() + 1;
}
return count;
}
Example call:
Pattern pattern = Pattern.compile("232");
int count = countMatches(pattern, "23232"); // Returns 2
If you want a non-regular-expression search, just compile your pattern appropriately with the LITERAL flag:
Pattern pattern = Pattern.compile("1+1", Pattern.LITERAL);
int count = countMatches(pattern, "1+1+1"); // Returns 2
You can number of occurrences using inbuilt library function:
import org.springframework.util.StringUtils;
StringUtils.countOccurrencesOf(result, "R-")
Increment lastIndex whenever you look for next occurrence.
Otherwise it's always finding the first substring (at position 0).
The answer given as correct is no good for counting things like line returns and is far too verbose. Later answers are better but all can be achieved simply with
str.split(findStr).length
It does not drop trailing matches using the example in the question.
public int indexOf(int ch,
int fromIndex)
Returns the index within this string of the first occurrence of the specified character, starting the search at the specified index.
So your lastindex value is always 0 and it always finds hello in the string.
try adding lastIndex+=findStr.length() to the end of your loop, otherwise you will end up in an endless loop because once you found the substring, you are trying to find it again and again from the same last position.
Try this one. It replaces all the matches with a -.
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int numberOfMatches = 0;
while (str.contains(findStr)){
str = str.replaceFirst(findStr, "-");
numberOfMatches++;
}
And if you don't want to destroy your str you can create a new string with the same content:
String str = "helloslkhellodjladfjhello";
String strDestroy = str;
String findStr = "hello";
int numberOfMatches = 0;
while (strDestroy.contains(findStr)){
strDestroy = strDestroy.replaceFirst(findStr, "-");
numberOfMatches++;
}
After executing this block these will be your values:
str = "helloslkhellodjladfjhello"
strDestroy = "-slk-djladfj-"
findStr = "hello"
numberOfMatches = 3
As #Mr_and_Mrs_D suggested:
String haystack = "hellolovelyworld";
String needle = "lo";
return haystack.split(Pattern.quote(needle), -1).length - 1;
Based on the existing answer(s) I'd like to add a "shorter" version without the if:
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int count = 0, lastIndex = 0;
while((lastIndex = str.indexOf(findStr, lastIndex)) != -1) {
lastIndex += findStr.length() - 1;
count++;
}
System.out.println(count); // output: 3
Here is the advanced version for counting how many times the token occurred in a user entered string:
public class StringIndexOf {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a sentence please: \n");
String string = scanner.nextLine();
int atIndex = 0;
int count = 0;
while (atIndex != -1)
{
atIndex = string.indexOf("hello", atIndex);
if(atIndex != -1)
{
count++;
atIndex += 5;
}
}
System.out.println(count);
}
}
This below method show how many time substring repeat on ur whole string. Hope use full to you:-
String searchPattern="aaa"; // search string
String str="aaaaaababaaaaaa"; // whole string
int searchLength = searchPattern.length();
int totalLength = str.length();
int k = 0;
for (int i = 0; i < totalLength - searchLength + 1; i++) {
String subStr = str.substring(i, searchLength + i);
if (subStr.equals(searchPattern)) {
k++;
}
}
This solution prints the total number of occurrence of a given substring throughout the string, also includes the cases where overlapping matches do exist.
class SubstringMatch{
public static void main(String []args){
//String str = "aaaaabaabdcaa";
//String sub = "aa";
//String str = "caaab";
//String sub = "aa";
String str="abababababaabb";
String sub = "bab";
int n = str.length();
int m = sub.length();
// index=-1 in case of no match, otherwise >=0(first match position)
int index=str.indexOf(sub), i=index+1, count=(index>=0)?1:0;
System.out.println(i+" "+index+" "+count);
// i will traverse up to only (m-n) position
while(index!=-1 && i<=(n-m)){
index=str.substring(i, n).indexOf(sub);
count=(index>=0)?count+1:count;
i=i+index+1;
System.out.println(i+" "+index);
}
System.out.println("count: "+count);
}
}
Matcher.results()
You can find the number of occurrences of a substring in a string using Java 9 method Matcher.results() with a single line of code.
It produces a Stream of MatchResult objects which correspond to captured substrings, and the only thing needed is to apply Stream.count() to obtain the number of elements in the stream.
public static long countOccurrences(String source, String find) {
return Pattern.compile(find) // Pattern
.matcher(source) // Mather
.results() // Stream<MatchResults>
.count();
}
main()
public static void main(String[] args) {
System.out.println(countOccurrences("helloslkhellodjladfjhello", "hello"));
}
Output:
3
here is the other solution without using regexp/patterns/matchers or even not using StringUtils.
String str = "helloslkhellodjladfjhelloarunkumarhelloasdhelloaruhelloasrhello";
String findStr = "hello";
int count =0;
int findStrLength = findStr.length();
for(int i=0;i<str.length();i++){
if(findStr.startsWith(Character.toString(str.charAt(i)))){
if(str.substring(i).length() >= findStrLength){
if(str.substring(i, i+findStrLength).equals(findStr)){
count++;
}
}
}
}
System.out.println(count);
If you need the index of each substring within the original string, you can do something with indexOf like this:
private static List<Integer> getAllIndexesOfSubstringInString(String fullString, String substring) {
int pointIndex = 0;
List<Integer> allOccurences = new ArrayList<Integer>();
while(fullPdfText.indexOf(substring,pointIndex) >= 0){
allOccurences.add(fullPdfText.indexOf(substring, pointIndex));
pointIndex = fullPdfText.indexOf(substring, pointIndex) + substring.length();
}
return allOccurences;
}
public static int getCountSubString(String str , String sub){
int n = 0, m = 0, counter = 0, counterSub = 0;
while(n < str.length()){
counter = 0;
m = 0;
while(m < sub.length() && str.charAt(n) == sub.charAt(m)){
counter++;
m++; n++;
}
if (counter == sub.length()){
counterSub++;
continue;
}
else if(counter > 0){
continue;
}
n++;
}
return counterSub;
}
🍑 Just a little more peachy answer
public int countOccurrences(String str, String sub) {
if (str == null || str.length() == 0 || sub == null || sub.length() == 0) return 0;
int count = 0;
int i = 0;
while ((i = str.indexOf(sub, i)) != -1) {
count++;
i += sub.length();
}
return count;
}
I was asked this question in an interview just now and I went completely blank. (Like always, I told myself that the moment the interview ends ill get the solution) which I did, 5 mins after the call ended :(
int subCounter=0;
int count =0;
for(int i=0; i<str.length(); i++) {
if((subCounter==0 && "a".equals(str.substring(i,i+1)))
|| (subCounter==1 && "b".equals(str.substring(i,i+1)))
|| (subCounter==2 && "c".equals(str.substring(i,i+1)))) {
++subCounter;
}
if(subCounter==3) {
count = count+1;
subCounter=0;
}
}
System.out.println(count);