ActiveState Code

Recipe 442460: Increment numbers in a string


Suppose one reference number on your invoice is "XYZ-001", then let this algorithm figure out that the next one should be "XYZ-002" or that "dsc_010.jpg" should become "dsc_011.jpg"

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import re
from string import zfill
numbers = re.compile('\d+')

def increment(s):
    """ look for the last sequence of number(s) in a string and increment """
    if numbers.findall(s):
        lastoccr_sre = list(numbers.finditer(s))[-1]
        lastoccr = lastoccr_sre.group()
        lastoccr_incr = str(int(lastoccr) + 1)
        if len(lastoccr) > len(lastoccr_incr):
            lastoccr_incr = zfill(lastoccr_incr, len(lastoccr))
        return s[:lastoccr_sre.start()]+lastoccr_incr+s[lastoccr_sre.end():]

    return s

def T(_):
    print "from",_, "to", increment(_)
if __name__=='__main__':
    T("10dsc_0010.jpg")
    T("dsc_9.jpg")
    T("0000001.exe")
    T("ref-04851")

Discussion

It works at least. Perhaps I haven't used the SRE's returned correctly but perhaps by posting this recipe I can get some feedback on that.

Comments

  1. 1. At 5:07 p.m. on 20 oct 2005, Chris Olds said:

    Simplification. Here's my version, which I think is simpler.

    /cco

    import re
    lastNum = re.compile(r'(?:[^\d]*(\d+)[^\d]*)+')
    
    def increment(s):
        """ look for the last sequence of number(s) in a string and increment """
        m = lastNum.search(s)
        if m:
            next = str(int(m.group(1))+1)
            start, end = m.span(1)
            s = s[:max(end-len(next), start)] + next + s[end:]
        return s
    
    def T(_):
        print "from",_, "to", increment(_)
    if __name__=='__main__':
        T("10dsc_0010.jpg")
        T("10dsc_0099.jpg")
        T("dsc_9.jpg")
        T("0000001.exe")
        T("9999999.exe")
        T("ref-04851")
    

Sign in to comment