Say I have a String made up of numbers, letters, and symbols,
String foo = "987abc<*(123";
How would I be able to find the index of the first number in the last set of numbers ("1"
, at index 6
) in String foo
– and if foo = "123"
, I would get the index of that first number again ("1"
, at index 0
). (And also have it return index 0
if foo = ""
)
I'm pretty inexperienced with RegEx-es and search patterns like that, alongside the fact that every way I have tried hasn't worked properly (most of the time causing a StringIndexOutOfBoundsException
).
What's a reliable, simple way of finding the index of the start of the last set of numbers in a String?
CodePudding user response:
Note: the '1' is at index 8 in your String.
If you don't want it it not necessary to use RegEx for this.
A method like this should do the job:
public static int findLastNumbersIndex(String s) {
boolean numberFound = false;
boolean charBeforeNumberFound = false;
//start at the end of the String
int index = s.length() - 1;
//loop from the back to the front while there are more chars
//and no nonDigit is found before a digit
while (index >= 0 && !charBeforeNumberFound) {
//when the first number was found, set the boolean flag
if (!numberFound && Character.isDigit(s.charAt(index))) {
numberFound = true;
}
//when already a number was found and there is any nonDigit stop the execution
if (numberFound && !Character.isDigit(s.charAt(index))) {
charBeforeNumberFound = true;
break;
}
index--;
}
return index 1;
}
The execution for different Strings:
public static void main(String[] args) {
System.out.println("\"987abc<*123\"" " index of lastNumberSet: " findLastNumbersIndex("987abc<*123"));
System.out.println("\"987abc<*123abc\"" " index of lastNumberSet: " findLastNumbersIndex("987abc<*123abc"));
System.out.println("\"987abc\"" " index of lastNumberSet: " findLastNumbersIndex("987abc"));
System.out.println("\"abc987\"" " index of lastNumberSet: " findLastNumbersIndex("abc987"));
System.out.println("\"987\"" " index of lastNumberSet: " findLastNumbersIndex("987"));
System.out.println("(Empty String)" " index of lastNumberSet: " findLastNumbersIndex(""));
System.out.println("\"abc\"" " index of lastNumberSet: " findLastNumbersIndex("abc"));
}
returns this output:
"987abc<*123" index of lastNumberSet: 8
"987abc<*123abc" index of lastNumberSet: 8
"987abc" index of lastNumberSet: 0
"abc987" index of lastNumberSet: 3
"987" index of lastNumberSet: 0
(Empty String) index of lastNumberSet: 0
"abc" index of lastNumberSet: 0
CodePudding user response:
You can get it using Regex named group
public static int indexOfLastNumber(String text) {
Pattern pattern = Pattern.compile("(\\d )(?!.*\\d)");
Matcher matcher = pattern.matcher(text);
return matcher.find() ? matcher.start() : -1;
}
and I used test cases from @csalmhof answer, thanks to him
public static void main(String[] args) {
System.out.println("\"987abc<*123\"" " index of lastNumberSet: " indexOfLastNumber("987abc<*123"));
System.out.println("\"987abc<*123abc\"" " index of lastNumberSet: " indexOfLastNumber("987abc<*123abc"));
System.out.println("\"987abc\"" " index of lastNumberSet: " indexOfLastNumber("987abc"));
System.out.println("\"abc987\"" " index of lastNumberSet: " indexOfLastNumber("abc987"));
System.out.println("\"987\"" " index of lastNumberSet: " indexOfLastNumber("987"));
System.out.println("(Empty String)" " index of lastNumberSet: " indexOfLastNumber(""));
System.out.println("\"abc\"" " index of lastNumberSet: " indexOfLastNumber("abc"));
}
Output, -1 for a text that has no numbers
"987abc<*123" index of lastNumberSet: 8
"987abc<*123abc" index of lastNumberSet: 8
"987abc" index of lastNumberSet: 0
"abc987" index of lastNumberSet: 3
"987" index of lastNumberSet: 0
(Empty String) index of lastNumberSet: -1
"abc" index of lastNumberSet: -1