Wednesday 18 November 2015

arcpy - Python method for finding a substring within a string


I converted a KML to a feature class and no longer have access to the symbology set in the original KML. I'm trying to re-create this by creating a new field that stores identifying information useful in creating the layer symbology.


There are three different 'keywords' in the original attribute table that would be useful in a control structure that determines the appropriate symbology type. I need to search the string for these keywords, but I'm having trouble.



The sample code below is just to get the control structure working -- I know I need to use an update cursor to change / add field addtributes.


Here is my code:


# Import ESRI Python module
import arcpy

# Declare variables used in this script
#featureClass = r'C:\arbitraryLocationOnDisk'
oldField = 'FolderPath'
newField = 'HabitatType' # Restricted by domain: HabitatType
# 1. Critical Habitat

# 2. Corridors and Key Habitat Areas
# 3. Global IBA's

rows = arcpy.SearchCursor(featureClass)
for row in rows:
fieldValue = row.getValue(oldField)

if fieldValue.find('Global'):
print 'Global IBA'
elif fieldValue.find('Corridors'):

print 'Corridors and Key Habbitat Areas'
elif fieldValue.find('Critical'):
print 'Critical Habitat'
else:
print 'Unrecognized habitat type: ' + fieldValue
del fieldValue
except:
arcpy.GetMessages()
finally:
del rows


The problem I'm experiencing is that after every single row, I'm getting 'Global IBA' despite the fact that not every row contains the substring 'Global'.



Answer



The reason why you're getting 'Global IBA' for every row is that Python's string.find() method returns an integer representing the substring's position within the string, not a boolean. When it can't find the substring, it returns -1, which evaluates to True in your if statement. This could also have the opposite effect; if the string begins with the specified substring, it will return zero, which evaluates to False in your if condition.


Here are some examples:


>>>> 'Global IBA'.find('Global')
0
>>>> bool('Global IBA'.find('Global'))
False
>>>> 'Global IBA'.find('gibberish')

-1
>>>> bool('Global IBA'.find('gibberish'))
True

Since you don't care about the substring's index, it's simpler just to use the 'in' operator:


if 'Global' in fieldValue:
print 'Global IBA'
elif 'Corridors' in fieldValue:
print 'Corridors and Key Habbitat Areas'
elif 'Critical' in fieldValue:

print 'Critical Habitat'
else:
print 'Unrecognized habitat type: ' + fieldValue

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...