List comprehensions... 2

2089
0
02-25-2016 07:29 AM
Labels (1)
DanPatterson_Retired
MVP Emeritus
4 0 2,089

The other blog on list comprehensions (or comprehensions more generally) is getting to big to edit and maintain easily, so consider this part 2.  Part I can be found at List comprehensions...

Standard field calculator function

Code block

def func(a,b):
    if (a == -99):
        if (b <> -99):
            ans = -97
        else:
            ans = -99
    else:
        if (b == -99):
            ans = -98
        else:
            ans = float(a) - b
    return ans

Expression box    func(( !Fld_0!, !Fld_1!))

Readings:

Review:

  • [ list comprehension ]
    • lc = [ x for x in 'abcd']
    • ['a', 'b', 'c', 'd']
  • ( generator)
    • gen = ( x for x in list('abcd') )
    • >>> gen.next()
    • 'a'
  • { set comprehensison }
    • sc = { x for x in 'abcdaabbccdd}
    • set(['a', 'c', 'b', 'd'])
  • { dictionary comprehension }
    • dc ={ x: x*2 for x in 'abcd'}
    • {'a': 'aa', 'c': 'cc', 'b': 'bb', 'd': 'dd'}

As a list comprehension expression you still have to use a code block since the field calculator doesn't support iterable objects etc.  You can also use a generator like in the second example.

Since a list comprehension returns a list, you need to append a slice notation ...  [0] ... to indicate that the first element in the list is returned.   Obviously, this isn't an issue since the data are process one row at a time and there will only be one value returned.  You can use a generator expression if you wish to skip the slicing notation.  Remember, square brackets for list comprehensions, round brackets for a generator  and curly brackets for set and dictionary comprehensions.

Now this thread https://community.esri.com/thread/171857   posed the interesting question of what to do when you have been consciensious and used multiple null values to represent several conditions of null.  In the example, -99, -98 and -97 were used.  The desire was to provide a reclassification of the nulls whilst doing "something" with the remaining values in the two fields that needed to be examined.  In the code examples above, it was decided to retain the null value ranges while performing a simple subtraction for non-null values.  The results are shown in the figure.

As a cautionary note, this example only works IF the returned values of the subtraction does not return values in the range -99 to -97.  Solution?? instead of using a base conversion of -98, I could have easily substituted -9998 (or something similar) which would have retained the intent of the nulls yet permitted the subtraction to proceed.

I should be obvious that all you need to do is find a base value for the null should be obvious that all you need to do is find a base value for the null.

List comprehension code blocks

Code block

def LC_func(a,b): 
   return [(a+abs(a-b)) if ((a-b)<=1) else min(a,(a-b))][0]
   

Expression box     LC_func( !Fld_0!, !Fld_1!)

OR

Code block 

def LC_func2(a,b): 
  return ( (a+abs(a-b)) if ((a-b)<=1) else min(a,(a-b)) )

Expression box      LC_func2( !Fld_0!, !Fld_1!)

Tabular output
LC_demo.png
About the Author
Retired Geomatics Instructor at Carleton University. I am a forum MVP and Moderator. Current interests focus on python-based integration in GIS. See... Py... blog, my GeoNet blog...
Labels