Extract particular values from field

503
20
Jump to solution
03-06-2020 01:13 PM
CCWeedcontrol
Regular Contributor

I need help with extract a particulate value from the field "PojectIinfo" field.  I need to only extract the value/characters of the letter B and the 10 digits after the B an place it in the field "BP".

There might be a space in that value as well, for example B24501000 space 0. The total characters would be 11; B plus 10 digits. I am thinking i need to use re.compile but i am uncertain on the code.

 

Current field looks like this.

New SFR w/Attached Garage, covered parch and patio B24501000 0  >>>Extract B24501000 0 to BP field

B34567000 0 30 X 48 Pole Barn >>>Extract B34567000 0 to BP field

NEW 22,778 SQ FT B33561000 0 Addition to existing hop building >>>Extract B33561000 0 to BP field

Residential B14356000 0 Storage>>>Extract B14356000 0 to BP field

0 Kudos
1 Solution

Accepted Solutions
JoshuaBixby
MVP Esteemed Contributor

The one constant appears to be an 8-digit number.  Assuming that is the case, the following regex should work to extract the 8-digit number plus 2 afterwards:

>>> l = [
... "New SFR w/Attached Garage, covered parch and patio B24501000 0",
... "B34567000 0 30 X 48 Pole Barn",
... "NEW 22,778 SQ FT B33561000 0 Addition to existing hop building",
... "Residential B14356000 0 Storage",
... "Single Family Res B34561000A0",
... "New SFR w/Attached Garage, covered parch and patio B24501000 0 "
... ]
>>>
>>> for i in l:
...   re.findall(r"\d{8}[ \w]\d", i)
...
['24501000 0']
['34567000 0']
['33561000 0']
['14356000 0']
['34561000A0']
['24501000 0']
>>> 

View solution in original post

20 Replies
DanPatterson_Retired
MVP Esteemed Contributor

s = !YourFieldName!

Field calculator expression for your field BP

s[s.index("B"):s.index("B")+11]  # ---- using slicing‍
CCWeedcontrol
Regular Contributor

I get Failure During processing.

0 Kudos
DanPatterson_Retired
MVP Esteemed Contributor

If you have <null> in the data field, you have to query first for "not null"

What expression did you put in exactly? 

You were using the field calculator with a python parser?

You replace what I had between the !...! marks with your source field name?

And your destination field is a text field, right?

0 Kudos
CCWeedcontrol
Regular Contributor
!PojectIinfo![!PojectIinfo!.index("B"):!PojectIinfo!.index("B")+11]
Yes text field
0 Kudos
JoeBorgione
MVP Esteemed Contributor

Just to be sure, these are open text fields, that do not follow any particular format, correct?  Looks like your'e dealing with building permits which is what I'm currently working with; just say know to free form text fields!

At any rate I just created a test table with two fields: freeText and bpField.  Here is the code for a search cursor that returns the values you provide above: turn it into an update cursor to update the 'other field' to newValue....

import arcpy

arcpy.env.workspace = r'J:\ProProjects\weedcontrol\Default.gdb'

table = 'testTable'

field = 'freeText'

with arcpy.da.SearchCursor(table,field)as cursor:
    for row in cursor:
        rowList = row[0].split(' ')
        for i in rowList:
            if i.startswith('B') and  i[1].isdigit():
                newValue = f'{i} 0'
                print(newValue)

#returns:

B24501000 0
B34567000 0
B33561000 0
B14356000 0
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
That should just about do it....
CCWeedcontrol
Regular Contributor

Yes a text field and no particular format.

I get the following.

if i.startswith('B') and  i[1].isdigit():

0 Kudos
JoeBorgione
MVP Esteemed Contributor

You do get it or don't get it?

That should just about do it....
0 Kudos
CCWeedcontrol
Regular Contributor

sorry about that. I get the following error.

IndexError: string index out of range

On line

if i.startswith('B') and  i[1].isdigit():

0 Kudos
JoeBorgione
MVP Esteemed Contributor

If you are getting an out of range error, that tells me that the list we make out of the field value has only 1 or 0 elements.  You can trap for that something like:

with arcpy.da.SearchCursor(table,field)as cursor:
    for row in cursor:
        rowList = row[0].split(' ')
        if len(rowList) < = 1:
           pass
        else:
           for i in rowList:

But from the sounds of it, you've got some funky funky stuff in there.  Hence my feelings on free text fields.  I hate 'em....

That should just about do it....