2

I have a field that holds a variety of strings. These strings were field names and corresponding values that were concatenated into a single field per feature. Using .split/indexing I was able to create a dictionary where values correspond to field names and values correspond to attributes.

attributes in field= '"xyz"="abc","ghi"="lmno"'

dict= {'xyz':'abc','ghi':'lmno'}

I am now at the point where I'm trying to feed the keys:values into a da.UpdateCursor where the key is the field and row= value. Block below is the last part of the script I'm struggling with. I keep getting an error: sequence size must match size of row.

i= 0
z= 0
n= 0

while i <= getCount:
    kI= dic.keys()[z]
    kiS= str(kI)
    vI= dic.values()[n]

    with arcpy.da.UpdateCursor(item,kiS)as cursor:
        for row in cursor:
            row= vI
            cursor.updateRow(row)
            i+= 1
            z+= 1
            n+= 1
4
  • 1
    It looks like it's at row = vI, it should be something like row[n] = vI. I would use the dictionary as-is rather than iterating as all your features would have the last value in the dictionary. Mar 17, 2017 at 1:14
  • 1
    Clobbering the row variable is very inappropriate.
    – Vince
    Mar 17, 2017 at 1:14
  • Also should point out that you define your dictionary as dict yet refer to it as dic later on in your while loop. It's also not a good idea to call your dictionary 'dict' because it is a python key word.
    – Fezter
    Mar 17, 2017 at 1:17
  • Thanks for the comments. I attempted earlier to use the row[n] with no success. And although I used dict for the written portion above it is referenced as dic throughout the extent of the written script. Mar 17, 2017 at 1:19

1 Answer 1

2

I believe you're trying to do something like this:

dict= {'xyz':'abc','ghi':'lmno'}

for key in dict.iterkeys():
    print key + "=" + dict[key]
    with arcpy.da.UpdateCursor(item,key) as cursor:
        for row in cursor:
            row[0] = dict[key]
            cursor.updateRow(row)

Updating each field with the value stored against it in the dictonary.. It would be better to update each field in the row in turn and store once:

dict= {'xyz':'abc','ghi':'lmno'}

with arcpy.da.UpdateCursor(item,list(dict.iterkeys())) as uCur: # list(dict.iterkeys()) is ['xyz','ghi']
    fRange = range(len(dict))    # range to iterate - in this case [0,1]
    fVals  = list(dict.values()) # list of values   - in ths case ['abc','lmno']
    for row in UCur:
        for Index in fRange:     # update each field by index in the lists
            row[Index] = fVals[Index]
        UCur.updateRow(row)

As the slowest part is the storing of the row this will work much quicker.

4
  • thanks so much. I'll try first thing tomorrow when get access to a computer with arc on it. I'll be sure to accept this as soon as I can. Mar 17, 2017 at 1:29
  • Just create a list outside of the for loop. It never changes because the field order is static...
    – Paul
    Mar 17, 2017 at 5:04
  • After running it hit an error stating for Index in fRange: TypeError: 'int' object is not iterable. Although I'm not sure of the hit on performance for doing this, prior I was able to run using while..in this case it would look like Index= 0 while Index <= fRange: row[Index]=fVals[Index] Index +=1. Will try to update with this later today unless you think there may be a way that will perform it better. Thanks Mar 17, 2017 at 17:54
  • Sorry, I forgot the range keyword. len(dict) returns an int which is not iterable but range(len(dict)) returns a range from 0 to the length of the dict minus one. I've fixed that in the code. Mar 19, 2017 at 21:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.