Select to view content in your preferred language

Appending data to an empty dictionary

6720
15
Jump to solution
03-27-2018 01:36 PM
VishalShah2
Occasional Contributor II

So I am currently working on a tool that the user needs to apply a query in order to the run the tool for the queried data. I am trying to get around that by creating a blank dictionary in the script and then appending data to it. The data comes from a field in a feature class. I have never done this before but in theory it should work the same as appending to lists correct?

hubFeatures = r'hub_locations'

hubDict = {}

These are my working variables for this. The field that I want the data from to append to the dictionary is called 'NAME' in the hubFeatures FC. I was thinking of using cursors to achieve this. Unless there is an alternative approach. The idea is to then use the items in the dictionary to apply a query to the necessary layers and complete the functionality of the tool using a for loop. That part I can do. Need some assistance in setting up the dictionary.

0 Kudos
15 Replies
VishalShah2
Occasional Contributor II

Awesome and that doesn't interfere with my definition query that I am applying afterwards. Thank you so much for your help Blake!

0 Kudos
BlakeTerhune
MVP Regular Contributor

Typically, no, it does not interfere. However, it can depend on how you're creating your query expression. Assuming my example valueDict above:

for i in valueDict:
    expression = "NAME = '{}'".format(valueDict[i])
    print expression‍‍‍‍‍‍‍‍‍

Output:

NAME = 'Some Name'
NAME = 'Another Name'
NAME = 'Name Example'
NAME = 'And Another‍‍‍‍'‍‍‍‍‍‍‍‍

This makes perfectly valid SQL.

However, If you do something like this:

names = tuple(valueDict.values())
expression = "NAME in{}".format(names)
print expression‍‍‍‍‍‍

Output:

NAME in(u'Some Name', u'Another Name', u'Name Example', u'And Another')‍‍

It will keep the u designation and it won't be valid SQL.

You would have to do something like:

names = tuple(str(i) for i in valueDict.values())
expression = "NAME in{}".format(names)
print expression‍‍‍‍‍‍

Output:

NAME in('Some Name', 'Another Name', 'Name Example', 'And Another')‍‍

But if you have exactly one name record in the dictionary, a single item tuple still has a comma at the end:

NAME in('Some Name',)‍‍‍

Which is not valid SQL.

The best would be something like:

names = ",".join("'{}'".format(i) for i in valueDict.values())
expression = "NAME in({})".format(names)
print expression‍‍‍‍‍‍

Output:

NAME in('Some Name','Another Name','Name Example','And Another')‍‍

EDIT:

Or, you could get rid of the u designation by converting row[0] to a plain string when you create the dictionary:

valueDict = {}
with arcpy.da.SearchCursor(sourceFC, ["NAME"]) as cursor:
    for enum, row in enumerate(cursor):
        valueDict[enum] = str(row[0])
VishalShah2
Occasional Contributor II

I didn't even think of the first way you had it set up.

What I used was this:

hubFeatures = r'hub_locations'

hubDict = {}

with arcpy.da.SearchCursor(hubFeatures, 'HubName') as cursor:
     for enum, row in enumerate(cursor):
         hubDict[enum] = row[0]

for hub in hubDict:
     valueHub = dict.get(hubDict, hub)
     hubQuery = "NAME = " + "'" + str(valueHub) + "'"
     hubLayer = arcpy.mapping.ListLayers(mxd, 'hub_locations')[0]
     hubLayer.definitionQuery = hubQuery
0 Kudos
BlakeTerhune
MVP Regular Contributor

On line 10, you've got the wrong syntax for get(). Should be:

valueHub = hubDict.get(hub)

But since you are iterating over the keys in the dictionary (as hub), you know the key exists so you don't need to use get()

0 Kudos
VishalShah2
Occasional Contributor II

Thank you so much Dan!

0 Kudos
DanPatterson_Retired
MVP Emeritus

do you have them in the right order ?

r = [[1, 'a'], [2, 'b'], [3, 'c']]

valueDict = {v[0]:(v[1:]) for v in r}

valueDict
{1: ['a'], 2: ['b'], 3: ['c']}

# ---- switch it up

valueDict2 = {v[1]:(v[0]) for v in r}

valueDict2
{'a': 1, 'b': 2, 'c': 3}‍‍‍‍‍‍‍‍‍‍‍‍‍