1
import arcpy, datetime
arcpy.env.overwriteOutput = True

# Number of days to subtract
tdelta = datetime.timedelta(days=21)    

fiberCable = r'C:\Users\broadhurstn\Documents\ArcGIS\Default.gdb\FIBERCABLE'
conduit = r'C:\Users\broadhurstn\Documents\ArcGIS\Default.gdb\CONDUIT'
fibercableToConduit = r'C:\Users\broadhurstn\Documents\ArcGIS\Default.gdb\FibercableToConduit'
unc = r'\\Bvweb104draco\e\08_Scripts\referenceScripts\Conduit Export\ConduitExports.gdb\TampaConduit'

# Populate a dictionary that maps segment ID to the placed/planned date
segment_dates = defaultdict(list)
with arcpy.da.SearchCursor(fiberCable, ['segmentid', 'bv_cable_placed_planned']) as cursor:
    for row in cursor:
        segment_dates[row[0]].append(row[1])

# Populate a dictionary that maps conduit ID to a two-item list containing segment ID and placed/planned date
ftcs = {}
with arcpy.da.SearchCursor(fibercableToConduit, ['conduitipid', 'segmentid']) as cursor:
    for row in cursor:
        # Use .get() so that it won't fail if a segment ID isn't in the dictionary
        ftcs[row[0]] = [row[1], segment_dates.get(row[1])]

# Populate conduit 'bv_placed_est' field and subtract 21 days       
with arcpy.da.UpdateCursor(unc, ['ipid', 'bv_placed_est']) as cursor:
    for row in cursor:
        ipid = row[0]
        for k,v in ftcs.items():
            if ipid == str(k):
                # tdelta will not work on null values
                if v[1] is not None:
                    row[1] = min(v[1]) - tdelta
                    cursor.updateRow(row)   

The above code and below feature class table produce a dictionary that fills as follows:

{u'248bdd3a-a13c-44b4-b592-b64a843fb0bc': [u'{2AC71409-C59E-49E1-A35B-61CD19885A2A}', datetime.datetime(2020, 1, 14, 0, 0)]}

How do I add a multiple values to the dictionary keys using the below feature class table and have it choose the earliest date of the bunch?

enter image description here

Notice how the value in the dictionary matches "segment ID" in this feature class. I want to have the the SearchCursor look at the current dictionary, see if there is a value that matches the "SegmentID" field values and append the EARLIEST "Cable Placed Planned" to it's corresponding dictionary item as a second value. There could be multiple 'Cable Placed Planned' dates in the form of a value associated with a key.

Expected output for the first item:

{u'248bdd3a-a13c-44b4-b592-b64a843fb0bc': [u'{2AC71409-C59E-49E1-A35B-61CD19885A2A}', datetime.datetime(2016, 1, 14, 0, 0), datetime.datetime(2017, 12, 14, 0, 0), datetime.datetime(2019, 10, 28, 0, 0)}, etc...

The key could have 1 value, or 20 values associated with it and I need to sift through those values for the earliest date and append it to the conduit feature class field.

Working code above only takes a single value per key, but can't deal with instances when there are numerous values that need to be associated with a key.

5
  • Looking at your expected output and screen shot why have you chosen 12/14/2017 and not 1/14/2017? How are you defining earliest? Earliest in each year?
    – Hornbydd
    Commented Jun 5, 2019 at 15:45
  • Have you tried using in to see if the key is already there, and then appending to the list, otherwise initialize it with a value that is a list with just one element. mkyong.com/python/python-check-if-key-exists-in-dictionary Commented Jun 5, 2019 at 15:46
  • @Hornbydd Earliest date period, so 1/14/2017 before 12/14/2017. this particular key/value should choose 1/14/2016 as the date to append to the key, as it's the earliest.
    – GIS_GOD
    Commented Jun 5, 2019 at 15:49
  • You should use defaultdict(list) like i showed you in your previous question. You cant change a normal dictionary while iterating over it. Are you saying you already have the dictionary with datetime.datetime(2020, 1, 14, 0, 0) and then want to add values from another feature class? What happened to the datetime value first added, cant see it in your example
    – Bera
    Commented Jun 5, 2019 at 16:03
  • @BERA I'm saying when the first dictionary 'segment_dates' gets populated with the date value, I need it to have logic in place to take the earliest date associated with that 'Segment ID'. There could be a single 'Segment ID' associated to one date, or numerous like in the case above of 'Segment ID' 2AC71409-C59E-49E1-A35B-61CD19885A2A. For the case above we'd want the 'segment_dates' dictionary to look like this '{u'{2AC71409-C59E-49E1-A35B-61CD19885A2A}': datetime.datetime(2016, 1, 14, 0, 0)}' where it's taking the earliest date of the bunch.
    – GIS_GOD
    Commented Jun 6, 2019 at 16:20

1 Answer 1

2

This line is essentially overwriting the entry in the ftcs dictionary within the loop:

ftcs[row[0]] = [row[1], segment_dates.get(row[1])]

Hence you ending up with just one date entry.

I think you need to explore the dictionary method has_key() to check for the existing entry then return the value (your list) with ftcs[row[0]] ,lets call it mylist, update mylist with the required date and then use the line such as below to overwrite the entry, now with your updated list.

ftcs[row[0]] = mylist
1
  • Used suggestions from Hornbydd and @BERA to arrive at the correct solution. The code has been updated in my initial post to the correct answer.
    – GIS_GOD
    Commented Jun 6, 2019 at 21:33

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.