Using update cursor with dictionary keys/values fails

579
6
08-28-2019 03:52 PM
JoeBorgione
MVP Esteemed Contributor

I've used Richard Fairhurst‌'s TurboCharging method on numerous occasions and today for some unknown reason I'm getting an error I've never seen:  

TypeError: 'int' object is not subscriptable  

and I'm not sure what I've done wrong:

fc = 'DeliveryData_2018'
updateFields = ['Zipcode','ClientCount']

edit = arcpy.da.Editor(ws)
edit.startEditing(False,False)
edit.startOperation()

        
with arcpy.da.UpdateCursor(fc,updateFields) as updateRows:
    for updateRow in updateRows:
       keyValue = updateRow[0]
       if keyValue in countDict2018:
           updateRow[1] = countDict2018[keyValue][0]
           updateRows.updateRow(updateRow)
edit.stopOperation()
edit.stopEditing(True)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

'''
countDict2018 is in the form of:

{'84006': 3,'84009': 14,'84020': 37,...}

'''‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I need to check for the value in  line 12 as my zipcode polygons have a few zipcodes that I don't serve; without that, it chokes on a zipcode value in the polygon fc that does not appear in the dictionary.

(End of the day blues...)

That should just about do it....
0 Kudos
6 Replies
RandyBurton
MVP Regular Contributor

Can it be assumed the 'ZipCode' field is text and will not be None, null, blank?  If not, you will need to do some checking before line 12.

And in line 12, looks like you are asking for the first element, but the dictionary value in the example isn't a list / tuple.

JoeBorgione
MVP Esteemed Contributor

Thanks Randy-  I will check the feature class for null values: yes they are text type.  I think the idea with that polygon fc was to be able to use zip+4 so it would have a '-' in it. That data pre-dates me.

I grabbed another script of mine from the archives that used the same line 12 and 13 but I can't remember what the dictionary looked like.  Maybe something like this would correct it:

keyValue = updateRow[0]
       if keyValue in countDict2018:
           dictValue = countDict2018.get(keyValue)
           updateRow[1] = dictValue
           updateRows.updateRow(updateRow)

Fresh start (and eyes) in the morning...

That should just about do it....
0 Kudos
DanPatterson_Retired
MVP Esteemed Contributor

'int' object is not subscriptable  

# ---- you think there is more than 1, but there isn't

a = 1

a[0]  # ---- do the slicy thing
Traceback (most recent call last):

  File "<ipython-input-2-6a1284577a36>", line 1, in <module>
    a[0]

TypeError: 'int' object is not subscriptable


# ---- you need to check that a list, tuple whatever-iterable
# has more than one value and correct for it

if isinstance(a, (int, float)):  # ---- do a check for non-iterable
    a = [a]                      # ---- make it an iterable of one
    

a[0]  # ---- now do the slicing
1

# ---- on to the next problem
JoeBorgione
MVP Esteemed Contributor

Knowing my dictionary is a single value per key, I went with:

dictValue = countDict2018.get(keyValue)
That should just about do it....
0 Kudos
RichardFairhurst
MVP Honored Contributor

You say that:

countDict2018 is in the form of:

{'84006': 3,'84009': 14,'84020': 37,...}

That means an example of the key is '84006' and an example of the value is 3.  So the value is an integer and all you need to do to access it is use: countDict2018['84006'].  You only add an index value like  countDict2018['84006'][0] when the dictionary value contains a list or tuple (which was assumed in my sample blog code since I was normally storing values in the dictionary from multiple fields).  So the code you wrote would only work  if:

countDict2018 is in the form of:

{'84006': [3],'84009': [14],'84020': [37],...}

or
countDict2018 is in the form of:

{'84006': (3),'84009': (14),'84020': (37),...}
JoeBorgione
MVP Esteemed Contributor

Even better.  Thanks RIchard!  ( and thanks for your methodology)

That should just about do it....
0 Kudos