Python嵌套更新游标和嵌套字典。那里';这一定是一个更简单的方法

Python嵌套更新游标和嵌套字典。那里';这一定是一个更简单的方法,python,dictionary,cursor,arcmap,Python,Dictionary,Cursor,Arcmap,我已经创建了一个从表中调用值的嵌套字典,需要使用该数据更新要素类的属性表。作为测试,我使用了两个硬编码字段,但我需要弄清楚如何自动获取featFields的长度,并使用该长度指示每个要更新字段的索引位置。因此,我将使用一个变量逐步遍历每一行的索引位置,而不是硬编码行[1],行[2]等以及'LOCDESC'和'RIMELEV' 我在Python中工作。最终目标是在ArcMap 10.2或10.3中使用工具箱 import arcpy arcpy.env.workspace = r"C:/SARP1

我已经创建了一个从表中调用值的嵌套字典,需要使用该数据更新要素类的属性表。作为测试,我使用了两个硬编码字段,但我需要弄清楚如何自动获取
featFields
的长度,并使用该长度指示每个要更新字段的索引位置。因此,我将使用一个变量逐步遍历每一行的索引位置,而不是硬编码
行[1]
行[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."
由于
行[n]
的(当前硬编码)迭代会逐步遍历
字段的值,因此您可以设置一个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.
请注意,“偏移量”-
行[1]应该使用
featFields[0]
等等--这需要考虑。

由于
行[n]
的(当前硬编码)迭代会逐步遍历
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.
注意“偏移量”-行[1]应该使用
字段[0]
等等--这需要考虑。

问题在于访问数据字典中的正确字段。最终代码访问外部键列表和内部键:值对列表,并设置变量(z)以保持两个列表中的索引号相等。谢谢你的帮助,艾丽卡

以下是有效的方法:

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."
问题在于访问数据字典中的正确字段。最终代码访问外部键列表和内部键:值对列表,并设置变量(z)以保持两个列表中的索引号相等。谢谢你的帮助,艾丽卡

以下是有效的方法:

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."

昨晚我尝试了这样的循环,但它抛出了一个运行时错误:“值类型与字段类型不兼容”。硬编码版本工作正常,所以我想知道嵌套逻辑是否有问题。我完全运行了您的代码,除了一个更改:我从范围(1,len(featFields)-1)中的j开始,以排除添加到索引位置0的键'FACILITYID'。再次得到那个错误。。。有人能告诉我原因吗?值类型不兼容错误听起来像是试图将字符串值放入数字字段(即,
RIMELEV
可能是字符串
'3'
而不是整数
3
)。我的直觉告诉我同样的事情。。。但是为什么硬编码的版本工作时没有错误呢?循环版本有什么不同?这就是我需要识别和修复的,我被难住了。和值不正确匹配有关吗?每次循环时,让它打印出
j
featFields[j]
的值,并确保它们是您希望看到的。使用
type()。这是字典:{u'WN010136':{'LOCDESC':u'IN STREET',RIMELEV':237.7352603},u'WN010134':{'LOCDESC':u'IN STREET',RIMELEV':234.0856613},u'WN010135':{'LOCDESC':u'IN STREET',RIMELEV':232.3809403},u'WN010133':{'LOCDESC u'IN STREET AT BRIDGE',RIMELEV':238 6215228},u'WN010130':{'LOCDESC':u'IN STREET','RIMELEV':250.7409211},u'WN010131':{'LOCDESC':u'IN STREET AT BRIDGE','RIMELEV':239.0950564}我昨晚尝试了这样的循环,但它抛出了一个运行时错误:“值类型与字段类型不兼容”。硬编码版本工作正常,所以我想知道嵌套逻辑是否有问题。我完全运行了您的代码,只有一个变化:我从范围(1,len(featFields)-1)中的j开始要排除添加到索引位置0的键“FACILITYID”。再次出现该错误…有人能告诉我原因吗?值类型不兼容错误听起来像是试图将字符串值放入数字字段(即,
RIMELEV
可能是字符串
'3'
而不是整数
3
).我的直觉说了同样的事情…但是为什么硬编码版本工作时没有错误?循环版本有什么不同?这就是我需要识别和修复的,我很困惑。与值不正确匹配有关吗?让它打印出
j
featFields[j]的值
每次执行循环时,请确保它们是您期望看到的。使用
type()
向您显示变量的数据类型(例如
featFields[j]
),以验证问题是否存在。这可能与嵌套字典顺序有关。这是字典:{u'WN010136':乌因街、里梅列夫、237.7352603、乌因街、里梅列夫、234.0856613、乌因街、里梅列夫、232.3809403、乌因街、里梅列夫、232.3809403、乌因桥、里梅列夫、238.6215228、乌因街、里梅列夫、130、乌因街、里梅列夫、里梅列夫、232.3809403、乌因桥、乌因街、乌因桥、乌因桥、乌因桥、乌因桥{'LOCDESC':u'IN STREET AT BRIDGE','RIMELEV':239.0950564}