Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Product code looks like abcd2343, how to split by letters and numbers?

I have a list of product codes in a text file, on each line is the product code that looks like:

abcd2343 abw34324 abc3243-23A

So it is letters followed by numbers and other characters.

I want to split on the first occurrence of a number.

like image 697
Blankman Avatar asked Jul 27 '10 01:07

Blankman


People also ask

How do you split a list between letters and digits in Python?

The split() method of the string class is fairly straightforward. It splits the string, given a delimiter, and returns a list consisting of the elements split out from the string. By default, the delimiter is set to a whitespace - so if you omit the delimiter argument, your string will be split on each whitespace.

What is a split in code?

Definition and Usage. The split() method splits a string into a list. You can specify the separator, default separator is any whitespace. Note: When maxsplit is specified, the list will contain the specified number of elements plus one.


2 Answers

import re s='abcd2343 abw34324 abc3243-23A' re.split('(\d+)',s)  > ['abcd', '2343', ' abw', '34324', ' abc', '3243', '-', '23', 'A'] 

Or, if you want to split on the first occurrence of a digit:

re.findall('\d*\D+',s) > ['abcd', '2343 abw', '34324 abc', '3243-', '23A'] 

  • \d+ matches 1-or-more digits.
  • \d*\D+ matches 0-or-more digits followed by 1-or-more non-digits.
  • \d+|\D+ matches 1-or-more digits or 1-or-more non-digits.

Consult the docs for more about Python's regex syntax.


re.split(pat, s) will split the string s using pat as the delimiter. If pat begins and ends with parentheses (so as to be a "capturing group"), then re.split will return the substrings matched by pat as well. For instance, compare:

re.split('\d+', s) > ['abcd', ' abw', ' abc', '-', 'A']   # <-- just the non-matching parts  re.split('(\d+)', s) > ['abcd', '2343', ' abw', '34324', ' abc', '3243', '-', '23', 'A']  # <-- both the non-matching parts and the captured groups 

In contrast, re.findall(pat, s) returns only the parts of s that match pat:

re.findall('\d+', s) > ['2343', '34324', '3243', '23'] 

Thus, if s ends with a digit, you could avoid ending with an empty string by using re.findall('\d+|\D+', s) instead of re.split('(\d+)', s):

s='abcd2343 abw34324 abc3243-23A 123'  re.split('(\d+)', s) > ['abcd', '2343', ' abw', '34324', ' abc', '3243', '-', '23', 'A ', '123', '']  re.findall('\d+|\D+', s) > ['abcd', '2343', ' abw', '34324', ' abc', '3243', '-', '23', 'A ', '123'] 
like image 64
unutbu Avatar answered Oct 12 '22 02:10

unutbu


This function handles float and negative numbers as well.

def separate_number_chars(s):     res = re.split('([-+]?\d+\.\d+)|([-+]?\d+)', s.strip())     res_f = [r.strip() for r in res if r is not None and r.strip() != '']     return res_f 

For example:

utils.separate_number_chars('-12.1grams') > ['-12.1', 'grams'] 
like image 44
Babak Ravandi Avatar answered Oct 12 '22 02:10

Babak Ravandi