Python 带有嵌套字典的嵌套更新游标。必须有更简单的方法
Python nested update cursor with nested dictionary. There's got to be an easier way
我创建了一个从 table 调用值的嵌套字典,我需要使用该数据更新特征 class 的属性 table。我让它与两个硬编码字段一起工作作为测试,但我需要弄清楚如何自动获取 featFields
的长度并使用它来指示要更新的每个字段的索引位置。因此,我不是硬编码 row[1]
、row[2]
等以及 'LOCDESC'
和 'RIMELEV'
,而是使用一个变量来遍历每个索引位置。
我在 Python 工作。最终目标是在 ArcMap 10.2 或 10.3 中使用的工具箱。
import arcpy
arcpy.env.workspace = r"C:/SARP10/MACP_Tool"
#Define fields to update and the field to use as join field
Table = "Test2.csv"
Input = "Test.gdb/MHs"
csvFields = ['Location_Details', 'Elevation']
featFields = ['LOCDESC', 'RIMELEV']
csvKey = "Manhole_Number"
featKey = "FACILITYID"
csvFields.insert(0, csvKey)
featFields.insert(0, featKey)
print csvFields
#Create dictionary to store values from the update table
UpdateDict = {}
#Iterates through the values in the table and stores them in UpdateDict
with arcpy.da.SearchCursor(Table, csvFields) as cursor:
for row in cursor:
UpdateDict[row[0]] = dict(zip(featFields[1:], row[1:]))
print UpdateDict
MHNum = len(UpdateDict) # gets # of MHs to be updated
MHKeys = UpdateDict.keys() # gets key values, i.e. MH numbers
print "You are updating fields for the following {} manholes: {}".format(MHNum, MHKeys)
#Iterates through feature class attribute table and updates desired attributes
with arcpy.da.UpdateCursor(Input, featFields) as cursor:
i = 0
z = 0
for row in cursor:
i += 1
for f in UpdateDict.keys():
if f == row[0]:
row[1] = UpdateDict.values()[z]['LOCDESC']#uses counter and subdict key to call correct value
row[2] = UpdateDict.values()[z]['RIMELEV']#uses counter and subdict key to call correct value
cursor.updateRow(row)
z +=1 #counter keeps track of rows and provides index location for dictionary
print "Updating {} of {} manholes in this submittal: {}.".format(z, MHNum, f)
else:
pass
print "Updated {} of {} rows.".format(MHNum, i)
print "Script completed."
由于 row[n]
的(当前 hard-coded)迭代遍历 featFields
的值,您可以设置一个 for 循环来遍历它们,例如:
if f == row[0]:
# loop set by length of featFields list
for j in range(0, len(featFields) - 1):
row[j + 1] = UpdateDict.values()[z][featFields[j]]
cursor.updateRow(row)
# etc.
请注意 "offset" -- row[1]
应该使用 featFields[0]
等等 -- 这需要考虑在内。
问题是访问数据字典中的正确字段。最终代码访问外键列表和内键列表:值对,并设置变量 (z) 以保持两个列表中的索引号相等。感谢您的帮助,@Erica!
这是有效的:
import arcpy
arcpy.env.workspace = r"C:/SARP10/MACP_Tool"
#Defines fields to update and the field to use as join field
Table = "Test2.csv"
Input = "Test.gdb/MHs"
csvFields = ['Location_Details', 'Elevation', 'Rim_to_Invert', 'Rim_to_Grade', 'Cover_Size', 'Wall_Material', 'Wall_Diam', 'Wall_Lining_Interior', 'Photo2_Link', 'MH_InspectReportLink'] #update table fields
featFields = ['LOCDESC', 'RIMELEV', 'RIMTOINVERT', 'RIMTOGRADE','COVERSIZE','WALLMAT','DIAMETER','LINERTYPE','HYPERLINK_PHOTO2','HYPERLINK_RPT']#fc field names
csvKey = "Manhole_Number"
featKey = "FACILITYID"
csvFields.insert(0, csvKey)
featFields.insert(0, featKey)
print "Your table contains the following fields to be updated: {}\n".format(str(csvFields))
#Process: Create dictionary to store values from the update table, iterate through values and store in UpdateDict
UpdateDict = {}
with arcpy.da.SearchCursor(Table, csvFields) as cursor:
for row in cursor:
UpdateDict[row[0]] = dict(zip(featFields[1:], row[1:]))
## debug print "You have created update dictionary 'UpdateDict': \n{}\n\n".format(UpdateDict)
MHNum = len(UpdateDict) # gets # of MHs to be updatedMHKeys = sorted(UpdateDict.keys()) # gets key values, i.e. MH numbers
MHKeys = UpdateDict.keys() #calls outer keys (MH numbers, which are join values) into a list of keys
MHVals = UpdateDict.values()#calls inner nested key:value pairs to a list
##debug print "Dictionary keys: {}\n\n Dictionary values: {}\n\n".format(str(MHKeys),str(MHVals))
print "You are updating fields for the following {} manholes: {}".format(MHNum, str(MHKeys))
#Process: Iterates through feature class attribute table and updates desired attributes
with arcpy.da.UpdateCursor(Input, featFields) as curs:
i = 0 #attribute table row counter
for row in curs:
i += 1
for f in MHKeys:
if f == row[0]:
z = MHKeys.index(f)#get index location in MHKeys
for y in range(0,len(featFields)-1):
row[y+1] = MHVals[z][featFields[y+1]]#use z to pull corresponding value in MHVals to correct key in MHKeys
print "Current MH: {} \nUpdating Values: {} \n\n".format(f, UpdateDict.values()[z])
curs.updateRow(row)
else:
pass
print "Updated {} of {} rows.".format(MHNum, i)
print "Script completed."
我创建了一个从 table 调用值的嵌套字典,我需要使用该数据更新特征 class 的属性 table。我让它与两个硬编码字段一起工作作为测试,但我需要弄清楚如何自动获取 featFields
的长度并使用它来指示要更新的每个字段的索引位置。因此,我不是硬编码 row[1]
、row[2]
等以及 'LOCDESC'
和 'RIMELEV'
,而是使用一个变量来遍历每个索引位置。
我在 Python 工作。最终目标是在 ArcMap 10.2 或 10.3 中使用的工具箱。
import arcpy
arcpy.env.workspace = r"C:/SARP10/MACP_Tool"
#Define fields to update and the field to use as join field
Table = "Test2.csv"
Input = "Test.gdb/MHs"
csvFields = ['Location_Details', 'Elevation']
featFields = ['LOCDESC', 'RIMELEV']
csvKey = "Manhole_Number"
featKey = "FACILITYID"
csvFields.insert(0, csvKey)
featFields.insert(0, featKey)
print csvFields
#Create dictionary to store values from the update table
UpdateDict = {}
#Iterates through the values in the table and stores them in UpdateDict
with arcpy.da.SearchCursor(Table, csvFields) as cursor:
for row in cursor:
UpdateDict[row[0]] = dict(zip(featFields[1:], row[1:]))
print UpdateDict
MHNum = len(UpdateDict) # gets # of MHs to be updated
MHKeys = UpdateDict.keys() # gets key values, i.e. MH numbers
print "You are updating fields for the following {} manholes: {}".format(MHNum, MHKeys)
#Iterates through feature class attribute table and updates desired attributes
with arcpy.da.UpdateCursor(Input, featFields) as cursor:
i = 0
z = 0
for row in cursor:
i += 1
for f in UpdateDict.keys():
if f == row[0]:
row[1] = UpdateDict.values()[z]['LOCDESC']#uses counter and subdict key to call correct value
row[2] = UpdateDict.values()[z]['RIMELEV']#uses counter and subdict key to call correct value
cursor.updateRow(row)
z +=1 #counter keeps track of rows and provides index location for dictionary
print "Updating {} of {} manholes in this submittal: {}.".format(z, MHNum, f)
else:
pass
print "Updated {} of {} rows.".format(MHNum, i)
print "Script completed."
由于 row[n]
的(当前 hard-coded)迭代遍历 featFields
的值,您可以设置一个 for 循环来遍历它们,例如:
if f == row[0]:
# loop set by length of featFields list
for j in range(0, len(featFields) - 1):
row[j + 1] = UpdateDict.values()[z][featFields[j]]
cursor.updateRow(row)
# etc.
请注意 "offset" -- row[1]
应该使用 featFields[0]
等等 -- 这需要考虑在内。
问题是访问数据字典中的正确字段。最终代码访问外键列表和内键列表:值对,并设置变量 (z) 以保持两个列表中的索引号相等。感谢您的帮助,@Erica!
这是有效的:
import arcpy
arcpy.env.workspace = r"C:/SARP10/MACP_Tool"
#Defines fields to update and the field to use as join field
Table = "Test2.csv"
Input = "Test.gdb/MHs"
csvFields = ['Location_Details', 'Elevation', 'Rim_to_Invert', 'Rim_to_Grade', 'Cover_Size', 'Wall_Material', 'Wall_Diam', 'Wall_Lining_Interior', 'Photo2_Link', 'MH_InspectReportLink'] #update table fields
featFields = ['LOCDESC', 'RIMELEV', 'RIMTOINVERT', 'RIMTOGRADE','COVERSIZE','WALLMAT','DIAMETER','LINERTYPE','HYPERLINK_PHOTO2','HYPERLINK_RPT']#fc field names
csvKey = "Manhole_Number"
featKey = "FACILITYID"
csvFields.insert(0, csvKey)
featFields.insert(0, featKey)
print "Your table contains the following fields to be updated: {}\n".format(str(csvFields))
#Process: Create dictionary to store values from the update table, iterate through values and store in UpdateDict
UpdateDict = {}
with arcpy.da.SearchCursor(Table, csvFields) as cursor:
for row in cursor:
UpdateDict[row[0]] = dict(zip(featFields[1:], row[1:]))
## debug print "You have created update dictionary 'UpdateDict': \n{}\n\n".format(UpdateDict)
MHNum = len(UpdateDict) # gets # of MHs to be updatedMHKeys = sorted(UpdateDict.keys()) # gets key values, i.e. MH numbers
MHKeys = UpdateDict.keys() #calls outer keys (MH numbers, which are join values) into a list of keys
MHVals = UpdateDict.values()#calls inner nested key:value pairs to a list
##debug print "Dictionary keys: {}\n\n Dictionary values: {}\n\n".format(str(MHKeys),str(MHVals))
print "You are updating fields for the following {} manholes: {}".format(MHNum, str(MHKeys))
#Process: Iterates through feature class attribute table and updates desired attributes
with arcpy.da.UpdateCursor(Input, featFields) as curs:
i = 0 #attribute table row counter
for row in curs:
i += 1
for f in MHKeys:
if f == row[0]:
z = MHKeys.index(f)#get index location in MHKeys
for y in range(0,len(featFields)-1):
row[y+1] = MHVals[z][featFields[y+1]]#use z to pull corresponding value in MHVals to correct key in MHKeys
print "Current MH: {} \nUpdating Values: {} \n\n".format(f, UpdateDict.values()[z])
curs.updateRow(row)
else:
pass
print "Updated {} of {} rows.".format(MHNum, i)
print "Script completed."