How to pair SearchCursor with UpdateCursor

6243
4
Jump to solution
03-13-2015 08:20 AM
deleted-user-MS0lE1F_0-sy
Occasional Contributor

I am having a little trouble figuring out where I am going wrong.

If I have "NW" in my direction field I want to move the point a certain distance, but if it is "NE"  I want the move to be opposite.  I think I am almost there but it will only take my last Update for all the features.

import arcpy


mxd = arcpy.mapping.MapDocument("CURRENT")


arcpy.env.overwriteOutput = True


fc = arcpy.GetParameterAsText(0)


NWxOffset = 200
NWyOffset = 200


NExOffset = -220
NEyOffset = -200


search = arcpy.SearchCursor(fc)
value = ""
for row in search:
    value = row.getValue("direction")
    with arcpy.da.UpdateCursor(fc, ["SHAPE@XY"]) as cursor:
        if value == "NW":
            for row in cursor:
                cursor.updateRow([[row[0][0] + NWxOffset, row[0][1] + NWyOffset]])
        elif value == "NE":
            for row in cursor:
                cursor.updateRow([[row[0][0] + NExOffset, row[0][1] + NEyOffset]])


arcpy.RefreshActiveView
0 Kudos
1 Solution

Accepted Solutions
IanMurray
Frequent Contributor

You shouldn't need to combine cursors.  You can use the update cursor to check the value of your direction field, then depending on the value of the direction field.

import arcpy
mxd = arcpy.mapping.MapDocument("CURRENT")
arcpy.env.overwriteOutput = True
fc = arcpy.GetParameterAsText(0)
NWxOffset = 200  
NWyOffset = 200  
NExOffset = -220  
NEyOffset = -200  
fields = ["direction" , "SHAPE@X", "SHAPE@Y"]
with arcpy.da.UpdateCursor(fc, fields) as cursor:
    for row in cursor:
        if row[0] == "NW":
            row[1] += NWxOffset
            row[2] += NWyOffset
        elif row[0] == "NE":
            row[1] += NExOffset
            row[2] += NEyOffset
        cursor.updateRow(row)
arcpy.RefreshActiveView

View solution in original post

4 Replies
IanMurray
Frequent Contributor

You shouldn't need to combine cursors.  You can use the update cursor to check the value of your direction field, then depending on the value of the direction field.

import arcpy
mxd = arcpy.mapping.MapDocument("CURRENT")
arcpy.env.overwriteOutput = True
fc = arcpy.GetParameterAsText(0)
NWxOffset = 200  
NWyOffset = 200  
NExOffset = -220  
NEyOffset = -200  
fields = ["direction" , "SHAPE@X", "SHAPE@Y"]
with arcpy.da.UpdateCursor(fc, fields) as cursor:
    for row in cursor:
        if row[0] == "NW":
            row[1] += NWxOffset
            row[2] += NWyOffset
        elif row[0] == "NE":
            row[1] += NExOffset
            row[2] += NEyOffset
        cursor.updateRow(row)
arcpy.RefreshActiveView
deleted-user-MS0lE1F_0-sy
Occasional Contributor

Ian,

   That's it, learned something new.  Thank you so much.

- Matt

0 Kudos
IanMurray
Frequent Contributor

The other important thing to notice about UpdateCursors is that when you want to update the value of field, you actually need to set its value, using the rows index value from the cursor.  Once you set all the values, you then use cursor.updateRow(row) to update all the values in that row, not individually like I believe you were trying in your code.  You could have used two cursors, but that makes it fairly slower.  If this was a first attempt at using cursors, it was a good try.

Darren Wiens​, since it returns SHAPE@XY as a tuple in his original code, he shouldn't have been able to adjust the features centroid since tuples are immutable correct, or does an update cursor allow you to update SHAPE@XY?  Curious if you know, if not I might investigate some.

DarrenWiens2
MVP Honored Contributor

I won't pretend to understand the inner workings of it (I usually use 'SHAPE@', as a convenient but wasteful practice), but I think that because cursor.updateRow updates the table value rather than changing the tuple itself, it works, like below.

>>> with arcpy.da.UpdateCursor("fc",'SHAPE@XY') as cursor:
...    for row in cursor:
...        cursor.updateRow([[row[0][0]+100, row[0][1]+1000]])

The value of row never changes within the loop.

Conversely, the following does not work, for the reason you've identified:

>>> with arcpy.da.UpdateCursor("fc",'SHAPE@XY') as cursor:
...     for row in cursor:
...         row[0][0] += 100
...         row[0][1] += 1000
...         cursor.updateRow([[row]])
...         
Runtime error 
Traceback (most recent call last):
  File "<string>", line 3, in <module>
TypeError: 'tuple' object does not support item assignment