4

I simply want to create a script which compares a list with the field names of a featureclass and if the fields do not exist in the featureclass add them.

My code works, but is very inefficient. How can I compare lists in a more efficient manner?

import sys,os
import arcpy
from arcpy import env

env.overwriteOutput = True

workspace = r"PATH_TO_WORKSPACE"
fc = r"PATH_TO_FEATURECLASS"


lst_fcfields = arcpy.ListFields(fc)
lst_myfields = ["field1","field2"]

for field in lst_fcfields:
        for myfield in lst_myfields:
                if field.name ==myfield:
                        print fc +" - same as - " 
                else:
                        print field.name + " - not same as - " + myfield
                        arcpy.AddField_management(fc, myfield, "TEXT", "", "", 255)

Ideally, I would like the script to work interactively and ask the user if they would like to delete the fields which vary from the list, but as far as I know there are no dialogs in arcpy.

3
  • 2
    For dialogs in python, try using Tkinter (wiki.python.org/moin/TkInter). If you're running this from the interactive window, you probably can't do it as easily as if you were using a stand alone script as a tool or outside of ArcMap. – Branco Jun 12 '15 at 12:39
  • 1
    just to point out that this is really a python question, not an arcpy question. python is full of wonderful objects like sets, lists, and dictionaries, so reading python documentation will help immensely with any arcpy code. just try searching "compare python lists" and you'll see! – mr.adam Jun 12 '15 at 15:58
  • I use filter and validation script for this – FelixIP Jun 13 '15 at 3:46
4

This is a perfect use for list comprehension (two times!):

lst_fcfields = [f.name for f in arcpy.ListFields(fc)]
lst_myfields = ["field1","field2"]

## this line is the answer to the question       ----------------
diff_fields = [i for i in lst_myfields if not i in lst_fcfields]
## compare lists using an if within list comprehension ----------

for field in diff_fields:
    arcpy.AddField_management(fc, field, "TEXT", "", "", 255)

diff_fields can be read as: "every item in lst_myfields if that item is not in lst_fcfields"

For interactivity, as @Branco says, this would be easy if it were a stand-alone script. I don't have experience with tkinter, but in the simple console you could use something like:

for field in diff_fields:
    print field
    choice = raw_input("  add this field to the feature class? y/n ")
    if choice.lower().startswith("y"):
        arcpy.AddField_management(fc, field, "TEXT", "", "", 255)
        print "  field added"
    else:
        print "  field not added"
0
13

Do a set difference:

s.difference(t) s - t new set with elements in s but not in t

Ex:

l1 = ['apple','banana', 'celentro', 'donut', 'elephant', 'film', 'gopher','hyena',1,2,3,4,5]
l2 = ['film', 'celentro', 'badger', 'tiger', 100, 2, 4, 16]

>>> set(l1).difference(set(l2))
set([1, 3, 'apple', 'gopher', 'hyena', 'donut', 'elephant', 'banana', 5])

>>> set(l2).difference(set(l1))
set([16, 'tiger', 100, 'badger'])

Here is the performance difference, measured with cProfile:

>>> l1 = range(10000)
>>> l2 = range(5, 10005)
>>> cProfile.run('[i for i in l1 if not i in l2]')
         2 function calls in 1.472 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    1.472    1.472    1.472    1.472 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


>>> cProfile.run('set(l1).difference(set(l2))')
          3 function calls in 0.009 seconds

    Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.003    0.003    0.009    0.009 <string>:1(<module>)
        1    0.006    0.006    0.006    0.006 {method 'difference' of 'set' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

For you you would do something like:

flds_to_add = set(lst_myfields).difference(set(lst_fcfields))
for field in flds_to_add:
  arcpy.AddField_management(fc, field, 'TEXT', '', '', 255)
1
  • 1
    +1 for @MakinFlippyFloppy's wonderful performance analysis. Thanks! that's really nice to know. – mr.adam Jun 12 '15 at 17:03
1

Maybe something like this.

import sys,os
import arcpy
from arcpy import env

env.overwriteOutput = True
workspace = r"PATH_TO_WORKSPACE"
fc = r"PATH_TO_FEATURECLASS"

lst_myfields = ["field1","field2"]

for field in [fieldfc.name for fieldfc in arcpy.ListFields(fc)]:
        if field in lst_myfields:
            print field +" - same as - "
        else:
            print field + " - not same"
            arcpy.AddField_management(fc, field, "TEXT", "", "", 255)

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.