-1

I have several sets of fields to populate based on other fields. The code below works, but I am wondering if there is a more Pythonic way to march through the i,j pairs? (Actual fieldnames are not this simple.)

i = ['FieldA1', 'FieldB1', 'FieldC1', 'FieldD1']
j = ['FieldA2', 'FieldB2', 'FieldC2', 'FieldD2']

if len(i) != len(j):
    arcpy.AddMessage("Error - i & j are not the same length")
    sys.exit()

for n in range(len(i)):
    fields = [i[n], j[n]]
    with arcpy.da.UpdateCursor(mySHP, fields) as cursor:
        for row in cursor:
            val = row[0]
            if float(val) == -999:
                row[1] = -999
            else:
                row[1] = float(val) / 100
            cursor.updateRow(row)
  • 2
    There's no need to make N passes through the table. Include all your columns in the field list and iterate within the for. – Vince Oct 29 '18 at 0:42
  • not sure what you mean--how will that iterate pairwise? (i.e., 1st run is with ['FieldA1', 'FieldA2']; second run is with ['FieldB1', 'FieldB2']; etc. – AlexS1 Oct 29 '18 at 0:47
  • 1
    How many rows are being updated? If it's less than 1000, it would be difficult to measure a difference; if it's more than 10 million, there might not be enough time to run a statistically relevant sample with your method before the next required OS patch reboot. – Vince Oct 29 '18 at 2:39
  • @Vince the dataset I did the run time tests on was about 200 pts; I used my code for other datasets up to about 1100 pts. I agree, performance doesn't matter for this case. Was just trying to use it as an opportunity to improve my Python syntax. – AlexS1 Oct 29 '18 at 2:59
  • 1
    Pythonic-ness should not be a goal if it means unnecessary I/O. – Vince Oct 29 '18 at 3:45
1

Since you have working code I think that this is a question that would be more on-topic at the Code Review Stack Exchange than here. However, the inclusion of ArcPy cursors may confuse that site so in this instance I will provide an answer.

I suspect that this code:

i = ['FieldA1', 'FieldB1', 'FieldC1', 'FieldD1']
j = ['FieldA2', 'FieldB2', 'FieldC2', 'FieldD2']
fields = i + j
halfNumFields = len(i)
with arcpy.da.UpdateCursor(mySHP, fields) as cursor:
    for row in cursor:
        for n in range(halfNumFields):
            if int(row[n]) == -999:
                row[n + halfNumFields] = -999
            else:
                row[n + halfNumFields] = float(row[n]) / 100
            cursor.updateRow(row)

would run faster than yours:

i = ['FieldA1', 'FieldB1', 'FieldC1', 'FieldD1']
j = ['FieldA2', 'FieldB2', 'FieldC2', 'FieldD2']

for n in range(len(i)):
    fields = [i[n], j[n]]
    with arcpy.da.UpdateCursor(mySHP, fields) as cursor:
        for row in cursor:
            val = row[0]
            if float(val) == -999:
                row[1] = -999
            else:
                row[1] = float(val) / 100
            cursor.updateRow(row)

Irrespective of whether it is more Pythonic or not, the way that I would become sure about whether it runs faster is by performance timing the two alternatives.

  • 1
    I have a suspicion that the 2nd would be slower... it calls updateRow more frequently and that is where I suspect the time is being taken. The first updates all the fields in the row in memory (fast) and then updates the whole row (slow) which commits to the feature class on disc with data handler and HDD access overhead. – Michael Stimson Oct 29 '18 at 1:43
  • 1
    Cool, thanks for the advice. I did some run time tests out of curiosity. There are a couple other processes running in the script, but I left everything the same and just swapped the above codes. Ran each 3x; they basically have the same run times... PolyGeo's version times: 0:00:29.363000, 0:00:29.393000, 0:00:28.980000 // My version times: 0:00:28.489000, 0:00:29.463000, 0:00:28.614000 – AlexS1 Oct 29 '18 at 2:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.