0

Python dictionaries really have me today. I've been pouring over stack, trying to find a way to do a simple append of a new value to an existing key in a python dictionary adn I'm failing at every attempt and using the same syntaxes I see on here.

This is what i am trying to do:

#cursor seach a xls file
definitionQuery_Dict = {}

for row in arcpy.SearchCursor(xls):

    # set some source paths from strings in the xls file
    dataSourcePath = str(row.getValue("workspace_path")) + "\\" + str(row.getValue("dataSource"))
    dataSource = row.getValue("dataSource")

    # add items to dictionary. The keys are the dayasource table and the values will be definition (SQL) queries. First test is to see if a defintion query exists in the row and if it does, we want to add the key,value pair to a dictionary.
    if row.getValue("Definition_Query") <> None:

        # if key already exists, then append a new value to the value list
        if row.getValue("dataSource") in definitionQuery_Dict:
            definitionQuery_Dict[row.getValue("dataSource")].append(row.getValue("Definition_Query"))
        else:
            # otherwise, add a new key, value pair
            definitionQuery_Dict[row.getValue("dataSource")] = row.getValue("Definition_Query")

I get an attribute error:

AttributeError: 'unicode' object has no attribute 'append'

But I believe I am doing the same as the answer provided here

I've tried various other methods with no luck with various other error messages. i know this is probably simple and maybe I couldn't find the right source on the web, but I'm stuck. Anyone care to help?

Thanks, Mike

Community
  • 1
  • 1
Mike
  • 4,099
  • 17
  • 61
  • 83

3 Answers3

3

The issue is that you're originally setting the value to be a string (ie the result of row.getValue) but then trying to append it if it already exists. You need to set the original value to a list containing a single string. Change the last line to this:

definitionQuery_Dict[row.getValue("dataSource")] = [row.getValue("Definition_Query")]

(notice the brackets round the value).

ndpu has a good point with the use of defaultdict: but if you're using that, you should always do append - ie replace the whole if/else statement with the append you're currently doing in the if clause.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Ughh...I knew I needed something like this. To set the values to a list. I think I jsut looked at too many examples and then I confused myself. This is exactly what I need. Thanks! – Mike Feb 26 '14 at 23:34
3

Your dictionary has keys and values. If you want to add to the values as you go, then each value has to be a type that can be extended/expanded, like a list or another dictionary. Currently each value in your dictionary is a string, where what you want instead is a list containing strings. If you use lists, you can do something like:

mydict = {}
records = [('a', 2), ('b', 3), ('a', 4)]

for key, data in records:
    # If this is a new key, create a list to store
    # the values
    if not key in mydict:
        mydict[key] = []
    mydict[key].append(data)

Output:

mydict
Out[4]: {'a': [2, 4], 'b': [3]}

Note that even though 'b' only has one value, that single value still has to be put in a list, so that it can be added to later on.

Marius
  • 58,213
  • 16
  • 107
  • 105
2

Use collections.defaultdict:

from collections import defaultdict

definitionQuery_Dict = defaultdict(list)
# ...
ndpu
  • 22,225
  • 6
  • 54
  • 69
  • So, just import defaultdict and then change my variable from definitionQuery_Dict = {} to definitionQuery_Dict = defaultdict(list)? If so, I am still gettting the same error.... – Mike Feb 26 '14 at 22:15