Take the 2-minute tour ×

I'm trying to take a string like "PR405j" and separate it into two strings. In this instance, the two strings would be "PR" and "405j." There are a variety of strings I have to do this to. Exmaples: "ACR498" would be "ACR" and "498", "FR707e" would be "FR" and "707e", "TY699l" would be "TY" and "699l" and so on and so forth.

The problem I'm having is separating the first part from the second part. The amount of characters on either side differs, and the second string (the one with the numbers) may or may not have alphabetic characters in there as well. The only commonality between all of these strings is that you can divide them based on the first instance of an integer.

I thought a for loop that goes through every character in the original string and builds two separate strings inside would work, but I could only think to base the separation on integers and alphabetic characters, which would make something like "PR405j" turn into "PRj" and "405".

I also thought the split string method would help, but there's no one character all these strings have in common.

Finally, I can't split the strings based on the numbers of alphabetic characters in the beginning of the string (say 2 for "PR405j") because there is variation between strings.

If anybody could help me with this, I'd greatly appreciate it. Thank you!

share|improve this question
The alternative to re would be ''.join(itertools.takewhile(operator.methodcaller('isalpha'), thestring)), ''.join(itertools.dropwhile(operator.methodcaller('isalpha'), thestring)), but don't use that. –  agf Nov 9 '11 at 19:50
And what do you want to have happen if (1) the string doesn't start with any alphabetics (2) the alphas are not followed by any numerics? –  John Machin Nov 9 '11 at 20:49
add comment

3 Answers

You can use regular expressions to do simple string matching such as this. The expression '(\D+)(.+)' is saying 'Extract one or more non-digits as the first group, then extract one or more other characters as the second.'

import re

inputs = ['PR405j']

for input in inputs:
    match = re.match('(\D+)(.+)', input)

    start = match.group(1)
    end = match.group(2)

    print input, start, end
share|improve this answer
You could probably get away with (.+) instead of (\d.+) –  NullUserException Nov 9 '11 at 19:44
@NullUserExceptionఠ_ఠ Good point, fixed. –  Zack Bloom Nov 9 '11 at 19:49
The one liner would be start, end = re.match(r'(\D+)(.+)', input).groups(). –  Andrew Clark Nov 9 '11 at 19:52
@F.J: Bad luck if there is no match. One-liners don't get much use in the real world. –  John Machin Nov 9 '11 at 20:46
@ZackBloom: OP wants to start with alphabetics, not non-digits. –  John Machin Nov 9 '11 at 20:50
show 3 more comments

EDIT: I misunderstood the question, thought you wanted 3 groups, not two. Zack Bloom's answer is more correct, but I'll leave this here as a reference in case someone has a similar question.

You can use re.split:

>>> re.split(r'(\d+)', 'PR405j')
['PR', '405', 'j']

The trick here is using a capturing group (with parentheses) as the regular expression to split by; this will cause the output to contain the portions that caused the split as well as the portions to either side of it. If you have a string with multiple groups of digits separated by non-digits, this will fully split the string:

>>> re.split(r'(\d+)', 'PR405j123abc')
['PR', '405', 'j', '123', 'abc']
share|improve this answer
That doesn't split PR405j into PR and 405j. –  agf Nov 9 '11 at 19:44
Yeah, just re-read the question and edited. –  dcrosta Nov 9 '11 at 19:45
add comment

re.split, like the rest of the answers. But you have to munge it to deal with the grouping:

import re
re.split(r'([a-zA-Z]+)', 'PR405j', 1)[1:]
share|improve this answer
add comment

Your Answer


