I have what should be a fairly straightforward operation failing in ArcGIS Pro 2.4, and cannot for the life of me work out why.
If the field "assettype" contains a portion of the search string, then set the value of assettype_groupup to the value I return.
Eg, if "assetttype" contains the string "Building |Residential |Large ", and I test whether it contains the term "Residential", and that evaluates to true, then return the string "Residential".
Currently the code does not seem to be returning any result / has no effect, and appears to run too quickly (2-3 seconds for 3,000,000 lines).
If I try a ternary statement, which means using a single term at a time, it seems to work just fine. I'd rather not take this approach as the if/elif possibilities could wind up being extensive in nature and I'd like to run the routine only once.
Can you see any obvious issues with the setup below
#Target Field Name
assettype_groupup
#Expression
func(!assettype!)
# Code block
def func(input):
if 'Residential' in input:
return 'Residential'
elif 'Industrial/Utilities' in input:
return 'Industrial/Utilities'
elif 'Transport/Infrastructure' in input:
return 'Transport/Infrastructure'
elif 'Conservation/National Park' in input:
return 'Conservation/National Park'
elif 'Recreational/Open Space' in input:
return 'Recreational/Open Space'
elif 'Mixed Use' in input:
return 'Mixed Use'
elif 'Community Use' in input:
return 'Community Use'
elif 'Rural/Primary Production' in input:
return 'Rural/Primary Production'
elif 'Special Use' in input:
return 'Special Use'
elif 'Unknown' in input:
return 'Unknown'
else:
''
I am not familiar with ArcGIS Pro, but do know Python fairly well.
In Python you should avoid naming variables or arguments the same as any
built-ins, and input()
is the name of a built-in function. Also, the line after
the final else:
, should be return ''
. Since that's not the case, your
function will effectively return None
when there are no matches, not the
empty string ''
(assuming that's what you intended).
With that in mind, the following would be a better way to write the function that would avoid both of the issues mentioned above:
TARGETS = (
'Residential',
'Industrial/Utilities',
'Transport/Infrastructure',
'Conservation/National Park',
'Recreational/Open Space',
'Mixed Use',
'Community Use',
'Rural/Primary Production',
'Special Use',
'Unknown',
)
# Code block
def func(info):
for target in TARGETS:
if target in info:
return target
else: # Nothing matched.
return ''
A more advanced, slightly shorter and likely much faster, way to do would be by using Python's re
regular expression module which is part of its standard library:
import re
regex = re.compile('|'.join(map(re.escape, TARGETS)))
# Code block
def func(info):
mo = regex.search(info)
return mo.group(0) if mo else ''
In Python 3.8.0+ it could be shortened a little bit more by taking advantage of PEP 572's new syntax for assignment expressions using :=
(aka the "walrus" operator) which was added beginning in that version:
import re
regex = re.compile('|'.join(map(re.escape, TARGETS)))
def func(info):
return mo.group(0) if (mo := regex.search(info)) else '' # Py 3.8.0+