10

How can I get the last integer "56" from String like ra12ke43sh56?

I have to modify the next value as ra12ke43sh57 so I want to get the last the integer value.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rakesh
  • 131
  • 1
  • 1
  • 3

6 Answers6

27
StringBuilder sb = new StringBuilder();
for (int i = str.length() - 1; i >= 0; i --) {
    char c = str.charAt(i);
    if (Character.isDigit(c)) {
        sb.insert(0, c);
    } else {
        break;
    }
}
String result = sb.toString();

or

Pattern p = Pattern.compile("[0-9]+$");
Matcher m = p.matcher(str);
if(m.find()) {
    result = m.group();
}

And then Integer.parseInt(result)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
5

Perhaps something like this is what you want (see also on ideone.com):

static String nextId(String id) {
    String[] parts = id.split("(?=\\d+$)", 2);
    final int L = parts[1].length();
    final int num = Integer.parseInt(parts[1]) + 1;
    return parts[0] + String.format("%0"+L+"d", num);
}
public static void main(String[] args) {
    String[] tests = {
        "jamesBond007", "ra12ke43sh57", "-42", "x888y999", "00000"
    };
    for (String test : tests) {
        System.out.println(nextId(test));
    }
    // prints "jamesBond008", "ra12ke43sh58", "-43", "x888y1000", "00001"
}

How it works

There are several things at work here:

  • Using String.split(String regex, int limit), limited to 2 parts
    • parts[0] is the static prefix, possibly empty
    • parts[1] is the sequence of digits at the end of the string
  • Using zero-width matching positive lookahead to split
    • (?=\d+$) matches a position where you can match \d+$
      • That is, digit character \d character class
      • ... repeated one-or-more times +
      • ... till the end of the string anchor $
  • Using String.format to preserve any leading zeroes
    • A format like %05d means:
      • 0 : pad with leading zeroes
      • 5 : width is 5
      • d : decimal integer conversion

Related questions

On lookarounds:

References

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • You're obviously in love with lookarounds :) but in this case the simple "(\\d+)$" would do too - just capture the id directly, instead of matching the start position of the id and splitting the string there. – Dimitris Andreou Jun 24 '10 at 12:00
4

Not an answer, just to mention that the "obvious" regular expressions for this (as posted above) have a nasty quadratic behavior in the worst case (I'm pretty sure you are not dealing with such degenerate cases though, but it's interesting in its own accord).

Here is a little graph I prepared: alt text http://img517.imageshack.us/img517/1158/imageerp.jpg

I used strings of the form "111..1111a2" There are J occurrences of '1'.

The reason of the bad performance is obvious: the matcher keeps seeing 1s and happily thinks it's going to succeed, and only when it finds a nearly the end it finds that a doesn't match $, so it goes all the way back, and starts at the second character.

Initially I thought that possessive quantifiers would help here, but it doesn't look straight-forward. Even if I write \d++, if I call matcher.find() it will still try to match the pattern starting from every index anyway, i.e. the outer loop takes no hint from the previous fails of possesive quantifiers. (Note this issue does not affect Matcher.matches() since that only tries to match at a single index, the start).

In this particular problem, to avoid this behavior we would have to reverse the string and search with a simple ^\\d+ pattern, or iterate the characters backwards and do a manual match.

Dimitris Andreou
  • 8,806
  • 2
  • 33
  • 36
  • This is another instance of Schlemiel the Painter's algorithm, http://en.wikipedia.org/wiki/Schlemiel_the_Painter%27s_algorithm, coined by our very own Joel Spolsky. – Peter Mortensen Jul 14 '10 at 18:44
3
String result = str.substring(str.replaceAll("[0-9]+$","").length());

Breaking this down, if str is ra12ke43sh56:

str.replaceAll("[0-9]+$","") 

returns all but the last set of digits, i.e. ra12ke43sh

substring of the length of this on the main string returns just the ending digits, i.e. 56.

0xdb
  • 3,539
  • 1
  • 21
  • 37
Jay Edgar
  • 31
  • 2
1
  public static String getLastDigits(String string) {
    String reverseTaskId = new StringBuilder(string).reverse().toString();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < reverseTaskId.length(); i++) {
        if (Character.isDigit(reverseTaskId.charAt(i))) {
            sb.insert(i, reverseTaskId.charAt(i));
        } else {
            break;
        }
    }
    return sb.reverse().toString();
}
0
public class PrefixId {

    public String getTransactionNumber() {

    String prevNumber = "123abc321";
    String incredNumber = "";
    for (int i = prevNumber.length() - 1; i >= 0; i--) {
        char ch = prevNumber.charAt(i);

        if (incredNumber.length() > 0 && !Character.isDigit(ch)) {
            break;
        } else if (Character.isDigit(ch)) {
            incredNumber = incredNumber + ch;
        }

    }
    if (incredNumber.length() > 0) {
        incredNumber = new StringBuffer(incredNumber).reverse().toString();
        prevNumber = prevNumber.replace(incredNumber, ""
                + (Long.parseLong(incredNumber) + 1));
    }
    return prevNumber;
}

public static void main(String[] args) {
    PrefixId prefixId = new PrefixId();
    System.out.println(prefixId.getTransactionNumber());

}

}

CoolBeans
  • 20,654
  • 10
  • 86
  • 101
Rakesh
  • 131
  • 1
  • 1
  • 3