Saturday 2 February 2019

arcgis desktop - UpdateCursor only takes last value of SearchCursor


I have this piece of code:



#written on python 2.7 for ArcGIS Desktop 10.2.2

import arcpy

#set to folder where features are located
arcpy.env.workspace = "c:\\Users\\python_ex" #on windows use \\ instead of /


#---------------------------
#define variables for cursor

#---------------------------


"""SEARCHCURSOR"""
"""SearchCursor (in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause})"""
#field taken as "identifier". i.e. if column1 == a, take the value from the same row of column2
stable = "test2.shp"
sfield = ["column1", "column2"]
#where clause will be written in SQL and not assigned to variable
#more information can be found here http://resources.arcgis.com/en/help/main/10.2/index.html#//018w00000011000000


"""UPDATECURSOR"""
"""UpdateCursor (in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause})"""
#field taken as "identifier". i.e. if column 1 == a, take the value of the SearchCursor and insert into same row, but column2
utable = "test.shp"
ufield = ["column1", "column2"]
#where clause will be written in SQL and not assigned to variable
#more information can be found here http://resources.arcgis.com/en/help/main/10.2/index.html#/UpdateCursor/018w00000014000000/



#--------------------------
#start the loop
#--------------------------

svalues = [] #create list to store the values from the searchcursor

with arcpy.da.SearchCursor(stable, sfield, """"column1" = 'aa'""") as scursor: #SQL queries in python are build that way http://resources.arcgis.com/en/help/main/10.2/index.html#//002z0000001r000000
for srow in scursor:
svalues.append(srow) #append values to list
print svalues

with arcpy.da.UpdateCursor(utable, ufield, """"column1" = 'aa'""") as ucursor: #if used with statement, no need to close all the cursors
for urow in ucursor:
ucursor.updateRow(svalues[-1]) #-1 always takes the last value of the list

I want to update every field in test.shp with each value found in test2.shp.


But, it takes only the last value found in the table of test2.shp and updates all the fields in test.shp with it.


Shouldnt the logic of the loop I created be: "take the first value that matches the criteria, go on to the updatecursor, update the first row matching the criteria and then go back to search and update the next row. etc"


Or am I totally mistaken?



Answer



Since the UpdateCursor is nested inside the SearchCursor, it will loop through the cursor once for each srow. What it's actually doing (I assume) is running the full UpdateCursor for every SearchCursor value, but you're only seeing the last value since that is the last time it runs.



Also, the UpdateCursor will not stop at the first match -- it is being asked to run through every urow (i.e., all rows where column1 is aa).


If you can assume the two features are in the same order, try breaking the two cursors into separate loops:


with arcpy.da.SearchCursor(stable, sfield, """"column1" = 'aa'""") as scursor:
for srow in scursor:
svalues.append(srow) #append values to list
print svalues
with arcpy.da.UpdateCursor(utable, ufield, """"column1" = 'aa'""") as ucursor:
for index, urow in enumerate(ucursor):
ucursor.updateRow(svalues[index])


If they aren't in the same order, a sort command prior to the loops could work, or comparing an additional value (e.g. the ObjectID) to ensure the values match up.


This actually might work better as a join and calculate field operation, unless this is just an exercise to learn cursors :)


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...