1

I'm running an update cursor on an in_memory feature class to remove blank (but not null) values as part of a larger process.

I wanted by update cursor to loop through my list of fields and if the value was '' or ' ' just replace it with a Null, however while it is finding the correct fields it's not updating the value.

If I explicitly refer to each item in the row e.g. row[1] it works as expected, but not if I try to loop through row.

This works:

with arcpy.da.UpdateCursor(AddressLayer, fieldList) as cursor:
    for row in cursor:
        arcpy.AddMessage(row)
        u = 0
        if i > 1000:
            break

        ##  THIS BIT DOESN'T WORK! ##
        #for r in row:
        #   if r == '' or r == ' ':
        #       arcpy.AddMessage("OID = {}, value = '{}'".format(row[0], r))
        #       r = None
        #       u = 1
        ## THE ABOVE DOESN'T WORK! ##

        ## ADDED BECAUSE THE ABOVE DOESN'T WORK ##
        r = 1
        while r < 9:
            if row[r] == '' or row[r] == ' ':
                arcpy.AddMessage("OID = {}, value = '{}'".format(row[0], row[r]))
                row[r] = None
                u = 1
            r+=1
        ## END OF ADDED BIT ##

        if u == 1:
            arcpy.AddMessage("Updating")
            cursor.updateRow(row)
        i+=1

enter image description here

But this (the commented section above) doesn't:

for r in row:
    if r == '' or r == ' ':
        arcpy.AddMessage("OID = {}, value = '{}'".format(row[0], r))
        r = None
        u = 1

enter image description here

What am I missing about the second code snippet that means it wouldn't work?

  • You are already looping through each field in your list of fields with the first loop method, why are you trying to loop through each attribute as if it was a list itself? – artwork21 Mar 22 '16 at 21:41
  • where am I looping through each field first? I'm looping through each row, then I want to loop through each field. The commented part didn't work so I added the loop after that – Midavalo Mar 22 '16 at 21:44
  • I usually use len(row[r].replace(" ","")) == 0 but you also need to be aware of any non-printing characters (like TAB : '\t') that could be in the column - especially if pasting/loading from Excel which uses TAB to show an empty cell. – Michael Stimson Mar 22 '16 at 22:08
  • To me my commented bit should do the same as my added bit (see edited code comments above) - Have I done something wrong that I'm not seeing that would make the first loop not work but the second one work? – Midavalo Mar 22 '16 at 22:20
3

Your commented code doesn't update anything because you are only changing the temporary value (r) rather than the list item (row[r])

Compare...

>>> list = ['a','b','c']
... for item in list:
...     if item == 'b':
...         item = None # changes to None, but immediately changes to next value in list
... print list
... 
['a', 'b', 'c']

with...

>>> list = ['a','b','c']
... for i, item in enumerate(list):
...     if item == 'b':
...         list[i] = None # changes the list item
... print list
... 
['a', None, 'c']
1

Something like this should do the trick:

with arcpy.da.UpdateCursor(AddressLayer, fieldList) as cursor:
    for row in cursor:
        rows.updateRow(map(lambda x: x if unicode(x).strip() != '' else None, row)) #explicitly check for blank strings, cast to unicode first to avoid type errors

I have had all kinds of problems with this in the past and found it is best to explicitly check for empty values as whitespace by stripping.

Haven't tested this exact snippet in a cursor, but it did pass this test:

>>> row = (' ', 'a', 2, 3, 4334.9, 'alla', 'rack', '', 'ball', '     ')
>>> map(lambda x: x if unicode(x).strip() != '' else None, row)
[None, 'a', 2, 3, 4334.9, 'alla', 'rack', None, 'ball', None]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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