Is there a way to derive values using the Search Cursor and then update another field with those values?

1403
15
10-10-2019 08:57 AM
RPGIS
by
Occasional Contributor III

Hi,

So I have a slight predicament for this given scenario. I need to take the last 4 characters from the x coordinate and do the same for the y coordinate. I then need to combine the two and from the combined values, update another field. I have something akin but I keep running into errors. I can get it to list a set of values that I need but trying to get the update cursor to update the records in the field is tricky.

if field.name == 'FACILITY_ID':
            print field.name

            for row in arcpy.da.SearchCursor(fc, ["FACILITY_ID", "SHAPE@X", "SHAPE@Y"], """FACILITY_ID IS NULL"""):
                rowx = str(row[1])
                rowy = str(row[2])
                x = rowx[0:4]
                y = rowy[0:4]
                xy = x + y
            for row in arcpy.da.UpdateCursor(fc, ["FACILITY_ID"], """FACILITY_ID IS NULL"""):
                row.updateRow([xy])
                print '{} = {}'.format(field.name, xy)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Any help on this would be greatly appreciated.

0 Kudos
15 Replies
JoshuaBixby
MVP Esteemed Contributor

What I did in the code with assigning values is commonly called sequence/iterable unpacking, sometimes people call it tuple unpacking.  In Python 3, it was greatly enhanced to make it more useful (PEP 3132 -- Extended Iterable Unpacking | Python.org ), but you can only use the new features with Pro.

0 Kudos
RPGIS
by
Occasional Contributor III

Thanks again Joshua. I didn't even know that it was possible to unpack a

sequence by simply assigning values to the sequence. I will try applying

that to some of the other scripts since I've been looking for that kind of

solution. So regardless of how many values are in a sequence, you can

quintessentially assign values to any of the values in the sequence.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

So regardless of how many values are in a sequence, you can quintessentially assign values to any of the values in the sequence.

I don't quite get what you are saying/asking, especially "assign values to any of the values."  Most values are singletons, so you don't assign values to values, but you do assign values to variables.

Regarding the question I think you are asking, the answer is no for Python 2 and sort of for Python 3.  With Python 2, the number of variables on the left must equal the length of the sequence.  With Python 3, you can utilize a wild card so the number of variables on the left don't have to equal the length of the sequence, but there are limits to what can be done with the wild card.

0 Kudos
RPGIS
by
Occasional Contributor III

Hi Joshua,

I have another question in regards to unpacking sequences. Is it possible to specify a range of sequences and then check to see if a certain condition is true for that range. So for instance,

with arcpy.da.UpdateCursor(fc, ["fieldA", "fieldB", "fieldC", "fieldD", "COLLECTED_BY"]) as cursor:                
            for abandoned, facid, locate, survey, collected in cursor:
                if abandoned is None or abandoned == '':
                    print field.name
                    abandoned = 'NO'
                    print '{} = {}'.format(field.name, abandoned)
                    
                elif facid is None or facid == '':
                    print field.name
                    x = str(abs(int(row[1])))[:4]
                    y = str(abs(int(row[2])))[:4]
                    facid = x + y # concatenate strings x and y
                    print '{} = {}'.format(field.name, x + y)

                elif (locate, survey, collected) is None or (locate, survey, collected) == '':
                    locate = 'GPS'
                    survey = 'SUBMETER GPS'
                    collected = 'CONSULTANT'
                    print '{} = {}, {}, {}'.format(field.name, locate, survey, collected)
                    
                elif locate is None and (survey, collected) is not None:
                    locate = 'GPS'
                    print '{} = {}'.format(field.name, locate)
                    
                elif locate == 'GPS' and (survey is None or survey == '') and collected == 'CONSULTANT'
                    survey = 'SUBMETER GPS'
                    print '{} = {}'.format(field.name, locate)
                    
                elif locate == 'FIELD CHECK' and (survey is None or survey == '') and collected == 'CLIFF':
                    survey = 'ORTHO'
                    print '{} = {}'.format(field.name, survey)
                    
                elif (locate, survey) is not None and collected is None or collected == '':
                    collected = 'CONSULTANT'
                    print '{} = {}'.format(field.name, collected)
                    
                else:
                    print 'No null fields'
                cursor.updateRow(abandoned, facid, locate, survey, collected)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

If this is by no means possible or you or Randy or anybody in general may have a better solution for this I would definitely like to hear it. I took a look at my previous script that I wrote and noticed I had the same lines of code repeating and thought that this solution( if it can be counted as one ) would be easier to utilize. Any thoughts or ideas on this would be very appreciated.

Robert

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Before getting into the question itself, there are some structural issues with your code I want to discuss first.

Many of your conditional checks in your elif statements are not working the way you think.  For example, neither of the following

(locate, survey, collected) is None
(locate, survey, collected) == ''

will ever evaluate to True.  Nothing within a tuple, list, or similar data structure will ever evaluate to None, not even an empty tuple.

>>> tuple() is None
False

The same holds for your empty string check.

If you are interested in checking whether all the tuple items are None, then use all() — Python 2.7.17rc1 documentation, or use any() — Python 2.7.17rc1 documentation if you are interested in checking if at least 1 is None.

>>> any(i is None for i in ('foo', 'bar', None))
True
>>> all(i is None for i in ('foo', 'bar', None))
False
>>> 

The use of any() and all() is complicated a little by the presence of None, since None is false-y and so are empty strings and zero.

RPGIS
by
Occasional Contributor III

Thanks Joshua,

I gave it some more thought this morning and took another look at the script. I was trying to figure out the best way to determine how to go about this script. Essentially I am trying to go through each of the fields and populate any null or blank values. I must have misunderstood what you meant by sequence unpacking and I think I improperly applied it.

As for my other issue, I have been trying to figure out the best way to identify blank values in a field. For some reason using none didn't seem to work and trying to use ' '  to see if it could identify those values didn't seem to work either. I will modify the script with your suggestions and see if that makes a difference. The script I posted was a modified version of another script. The other script has each field broken down so I will modify that one. I will take a look at the link one I get a chance. I am juggling several things so I have been pretty busy and that is part of the reason I am looking to automate several tasks.

0 Kudos