Using Lists with arcpy.da.UpdateCursor

5774
16
07-13-2018 07:56 AM
deleted-user-_7x2iiEJ9SpB
Deactivated User

I am trying to use arcpy.da.UpdateCursor to find and replace old values in a field with new values.  I have made it work but I will ended up with an ridiculously lard if\elif statement (notice below that I stopped after the first 2 items in the list).  I would like to avoid this by iterating through both list to update the field.  I have tried without any luck.  Any suggestions?  Code is attached.

0 Kudos
16 Replies
JoshuaBixby
MVP Esteemed Contributor

Assuming the mapping between the two life cycle status lists is one to one based on position in the list, the following will work:

import arcpy


fc = r'G:\pworks\assetmanagement\Local Gov Info Model\Wastewater\Inputs\Valve_Schema.gdb\SControlValve'

LifeCycleStatus1 = ["ABN", "ACT","AB","CHGORD","DEM","INA","OTH","PRP","RMV","UNK","FV", "FD"]
LifeCycleStatus2 = ["Abandoned","Active","As Built","Change Order","Demolished","Inactive","Other","Proposed","Removed","Unknown","Field Verification Required","Future Development"]


    
try:    
    cursor = arcpy.da.UpdateCursor(fc, ["LIFECYCLESTATUS"])
    for row in cursor:
        row[0] = LifeCycleStatus2[LifeCycleStatus1.index(row[0])]
        cursor.updateRow(row)
    del row 
    del cursor
except RuntimeError:
    pass
VinceAngelo
Esri Esteemed Contributor

Please remember to post code as ASCII text (formatted appropriately), so that those who would help you don't need to retype your code.

- V

deleted-user-_7x2iiEJ9SpB
Deactivated User

Vince Angelo‌ thanks for the heads up!  How do I embed the code like Joshua Bixby‌ did?

0 Kudos
JoeBorgione
MVP Emeritus

Click on the three dots above:

Click on the resulting More button and choose Syntax highlighter.  Pick the language of choice, and paste your code in the window.  Click Ok button at the bottom of the window...

That should just about do it....
RandyBurton
MVP Alum

To use a dictionary instead of a list (assuming the mapping between your two lists), something like this should also work:

import arcpy

fc = r'G:\pworks\assetmanagement\Local Gov Info Model\Wastewater\Inputs\Valve_Schema.gdb\SControlValve'

LCStatus = {
    'ABN': 'Abandoned',
    'ACT': 'Active',
    'AB': 'As Built',
    'CHGORD': 'Change Order',
    'DEM': 'Demolished',
    'INA': 'Inactive',
    'OTH': 'Other',
    'PRP': 'Proposed',
    'RMV': 'Removed',
    'UNK': 'Unknown',
    'FV': 'Field Verification Required',
    'FD': 'Future Development'
    }
    
try:    
    cursor = arcpy.da.UpdateCursor(fc, ["LIFECYCLESTATUS"])
    for row in cursor:
        row[0] = LCStatus[row[0]]
        cursor.updateRow(row)
    del row 
    del cursor
except RuntimeError:
    pass‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
deleted-user-_7x2iiEJ9SpB
Deactivated User

Thanks for all the responses!  Right after I posted this I figured it out how to do it this way.  Any suggestions on adding an elif statement that will tell the user if there are any values in the field that are not in the list?  Example: "ANB" instead of "ABN"

import arcpy

# My Feature Class that I want to use
fc = arcpy.GetParameterAsText(0)

# My List of old and new values
LifeCycleStatus1 = ["ABN", "ACT","AB","CHGORD","DEM","INA","OTH","PRP","RMV","UNK","FV", "FD"]
LifeCycleStatus2 = ["Abandoned","Active","As Built","Change Order","Demolished","Inactive","Other","Proposed","Removed","Unknown","Field Verification Required","Future Development"]

try:
    i=0
    for life in LifeCycleStatus1:
        cursor = arcpy.da.UpdateCursor(fc, ["LIFECYCLESTATUS"])
        for row in cursor:    
            if row[0] == LifeCycleStatus1[i]:
                row[0] = LifeCycleStatus2[i]
                cursor.updateRow(row)
        i+=1
except RuntimeError:
    pass
          ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
JoeBorgione
MVP Emeritus
#logic:

if row[0] in listname:
  do something
elif row[0] in listname2:
  do something else
else:
  print 'Not in either list...'
That should just about do it....
RandyBurton
MVP Alum

For the dictionary approach, a check would be something like:

    for row in cursor:
        if if row[0] not in LCStatus.keys():
            # print error message and keep original value
            print "{} not in list".format(row[0])
        else: # update value
            row[0] = LCStatus[row[0]]
            cursor.updateRow(row)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
RandyBurton
MVP Alum

I notice in your second code posting, you are running multiple update cursor loops, once for each item in your list (line 12).  With either the indexing solution from Joshua or the dictionary solution, only a single pass with an update cursor is needed and is more efficient.