Select to view content in your preferred language

Custom Sort Fields and Iterate through to Assign Sequential Sort IDs

696
6
Jump to solution
01-31-2024 09:58 AM
TownofSandwichGISTechnician
New Contributor II

Python version: 3.9.18

I am trying to identify drainage structures that failed two inspections in a row.  To do so, I am making a copy of the related inspections table, then sort it by "NewGUID" (id field that ties inspections to parent drainage structures" and "date_" descending.  I have tested this workflow manually, and am now looking to automate it, but I'm having trouble.  Sorting by two fields is only available with the Advanced license, which I do not have.

After doing some research, I found what appears to be a similar situation here:

https://community.esri.com/t5/python-questions/increment-field-in-sorted-table/td-p/514221

I took the draft code provided by @RichardFairhurst and adapted it to my features and fields, and it now looks like this:

import arcpy

sourceFC = r"Z:\Projects\StormwaterInspectionsSelection\StormwaterInspectionsSelection.gdb\InspectionsCustomSorted20240130" 
sourceFieldsList = ['NewGUID', 'date_', 'OBJECTID']

# Use list comprehension to build a dictionary from a da SearchCursor 
valueDict = {tuple(r[0:]):0 for r in arcpy.da.SearchCursor(sourceFC, sourceFieldsList, sql_clause=(None, "ORDER BY NEWGuid, date_ DESC"))}

counter = 0
for item in sorted(valueDict.keys):
    counter += 1
    valueDict[item] = counter

sourceFieldsList.append("SortID")

with arcpy.da.UpdateCursor(sourceFC, sourceFieldsList, sql_clause=(None, "ORDER BY NEWGuid, date_ DESC")) as updateRows: 
    for updateRow in updateRows: 
        keyValue = tuple(updateRow[0:-1]) 
        # verify that the keyValue is in the Dictionary 
        if keyValue in valueDict:
            updateRow[-1] = valueDict[keyValue]
            updateRows.updateRow(updateRow)
del valueDict

When I run that, I receive this error message:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
In  [38]:
Line 10:    for item in sorted(valueDict.keys):

TypeError: 'builtin_function_or_method' object is not iterable
---------------------------------------------------------------------------

I searched online for that error and it seems that sorted is a built-in function and apparently can't be iterated.  Is there a way around this?

Please let me know if there's any more information needed.  Any help would be greatly appreciated!

0 Kudos
1 Solution

Accepted Solutions
RichardFairhurst
MVP Honored Contributor

As I recall, the sorted function may fail if any value it is trying to sort is None, since the sorted function must compare all values to each other to determine the order of the values, and None cannot be compared to other actual values the way that underlying function is written.  Since one of the fields making up your tuple key is a date field I imagine it can contain None values.  In any case you could print the keys prior to the sorted function to determine what the actual key values are to see if this may explain the code behavior.

 

You can try using a value substitution in your list comprehension as shown in the top reply to this post: https://stackoverflow.com/questions/30976124/sort-when-values-are-none-or-empty-strings-python

View solution in original post

6 Replies
RichardFairhurst
MVP Honored Contributor

As I recall, the sorted function may fail if any value it is trying to sort is None, since the sorted function must compare all values to each other to determine the order of the values, and None cannot be compared to other actual values the way that underlying function is written.  Since one of the fields making up your tuple key is a date field I imagine it can contain None values.  In any case you could print the keys prior to the sorted function to determine what the actual key values are to see if this may explain the code behavior.

 

You can try using a value substitution in your list comprehension as shown in the top reply to this post: https://stackoverflow.com/questions/30976124/sort-when-values-are-none-or-empty-strings-python

BlakeTerhune
MVP Regular Contributor

I tested this and confirmed @RichardFairhurst is correct, but I get a different error

TypeError: '<' not supported between instances of 'NoneType' and 'str'

I think it's a syntax issue. There should be open and closing parenthesis after keys.

for item in sorted(valueDict.keys()):

DanPatterson
MVP Esteemed Contributor

like in my example


... sort of retired...
0 Kudos
RichardFairhurst
MVP Honored Contributor

I agree about the parentheses.  As my original post indicated, the code was untested.   The post was intended to show the structure of how I typically tackle this kind of problem, but I must not have had time to design a real world test case to do an actual debug of the code at that time.

 

Anyway, I hope you have gotten what you needed.

TownofSandwichGISTechnician
New Contributor II

Thank you, @RichardFairhurst! There were a few records that didn't have a date_ value, and one that didn't have a NewGUID.  I resolved those, and added the parenthesis, as suggested  by @DanPatterson and @BlakeTerhune.  The script ran nearly instantly.  Thank you all for your help!

Josh

0 Kudos
DanPatterson
MVP Esteemed Contributor

keys()

z = {3: 0, 2: 5, 1:9}

for i in sorted(z.keys()):
    print(i)
    
1
2
3

   perhaps 


... sort of retired...