2

Working in arcgis desktop 10.2, I use python scripts to split some strings, found in an attribute table. Most of them were quite easy to split, but here is one that i could't manage to break.

string_example = "123a456"

I need to find were the first letter appears. Knowing it's position I will test if everything left from that letter are numbers AND everything right from that letter are numbers. If so i will write each part of the string in a new field.

FieldA = "123a456"

find the first letter, test if it is surrounded by numbers

FieldB= "123"

FieldC= "a"

FieldD= "456"

There are variations of the string, plenty of them: "12a1","12A1", "123ab1234", "a123b456". I need to find the structure: number-letter-number.

2
  • 1
    It's a bit unclear on how the string variations need to be handled. For example, would "123ab1234" be "123", "ab", "1234" or "123", "a", "b1234"? And would "a123b456" be "a", "123b456" or "a", "123", "b", "456"? Jan 28, 2015 at 14:58
  • This is a python question not an arcgis question. its belongs on stackoverflow. Jan 28, 2015 at 15:01

2 Answers 2

2

I would use regular expressions for this. You can use this in an arcpy script to update the field by setting the m.group(index) to be the field value. It is of str type.

import re
reload (re)

r = re.compile("([0-9]+)([a-zA-Z]+)([0-9]+)")
m = r.match("123ab1234")
if m:
    print m.group(1)
    print m.group(2)
    print m.group(3)

else:
    print "no match"
6
  • it works. i still have to work a bit to filter some messy data. i saw this value "123a1,1,2,3,4,5". It populated my 3 columns as "123", "a" and "1", but ",1,2,3,4,5" remained as "junk". A few conditions will do the job. The idea is there, thank you! Jan 28, 2015 at 14:54
  • Regular expressions can get really big and look crazy at some point. If it is a one-time job, consider filtering the fields first where there are commas or dots to avoid messing up with regular expressions (with list comprehension as here stackoverflow.com/questions/14411633/…). Jan 28, 2015 at 15:02
  • i have this problem now/ I am trying to compare the length of the string with the length of m. This way, if len("123ab1234") == len(m.group()) then there are no other values after the initial number-letter-number sequence. In IDLE it worked, but when i try to run it in arcmap's python window i get this error: Runtime error Traceback (most recent call last): File "<string>", line 16, in <module> AttributeError: 'NoneType' object has no attribute 'group'. Jan 28, 2015 at 15:25
  • Because you have to use a parameter for the m.group() function, otherwise you get only a group object. Like m.group(0). Group stores the part you found with the regex
    – Martin
    Jan 28, 2015 at 15:30
  • m.group() returns all the groups. the problem was that i had to declare the length of m after testing " if m: " Jan 28, 2015 at 15:39
2

To split a string into a list of numbers you can use regex in this way as well:

import re

s = re.split('[a-z]+', '123ab987')
print s
['123', '324']

and for your , problem you can use this regex:

s=re.split('[a-z|,]+', '123bc324,1,3,4')
print s
['123', '324', '1', '3', '4']

but you have to be a bit carefull. Because if the first/last character is also a letter, the list will return an empty value as the first/last list entry. If you want to delete it just check the list for this value:

 s = re.split('[a-z|,]+', 'a123bc324,1,3,4a')
 print s
 ['', '123', '324', '1', '3', '4', '']    

 if s[0] =='': # first ''
     s.pop(0)
 if s[-1] == '': # last ''
     s.pop(-1)

 print s
 ['123', '324', '1', '3', '4']

Like this you can use for example a string like 12b23c123. The advantage is that you dont need the m.group because re.split() returns directly a list.

Not the answer you're looking for? Browse other questions tagged or ask your own question.