2016-01-02 11 views
1

Я создал вложенные словарные значения, вызывающие из таблицы, и мне нужно обновить таблицу атрибутов для класса объектов с использованием этих данных. У меня есть работа с двумя жестко закодированными полями в качестве теста, но мне нужно выяснить, как автоматизировать получение длины featFields и использовать это для указания позиции индекса для каждого обновляемого поля. Итак, вместо жесткого кодирования row[1], row[2] и т. Д. И 'LOCDESC' и 'RIMELEV', я бы использовал переменную, чтобы перейти через позиции индекса для каждого из них.Вложенный курсор обновления Python с вложенным словарем. Должен быть более простой способ

Я работаю на 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." 

ответ

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

Поскольку (в настоящее время жестко) итерация row[n] шагов через значения featFields, вы можете создать цикл, который перебирает их обоих, что-то вроде:

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] и т. д. - это необходимо учитывать.

+0

Я попробовал цикл вроде этого прошлой ночью, но он бросает RuntimeError: «Тип значения несовместим с типом поля». Жестко закодированная версия работает отлично, поэтому мне интересно, есть ли проблема с вложенной логикой. Я запустил ваш код точно, за исключением одного изменения: я начал с j в диапазоне (1, len (featFields) -1), чтобы исключить ключ FACILITYID, добавленный в позицию индекса 0. Получение этой ошибки снова ... может кто-нибудь сказать мне Зачем? –

+0

Ошибка типа несовместимого типа _value напоминает, что она пытается поместить строковое значение в числовое поле (т. Е. 'RIMELEV' может быть строкой' '3'' вместо целых чисел' 3'). – Erica

+0

Мой инстинкт говорит то же самое ... но тогда почему жестко закодированная версия работает без ошибок? Что по-другому в зацикленной версии? Это то, что мне нужно для идентификации и исправления, и я в тупике. –