Hello SO!
I am working on a circular problem. In this problem, we have objects that are put on a ring of size MAX
, and are assigned IDs from (0 to MAX-1).
I have three simple functions to test for range inclusions. inRange(i,j,k) tests if i is in the circular interval [j,k[ (Mnemonic is i inRange(j,k)). And I have the same for ranges ]j,k[ and ]j,k].
Code in those three methods look duplicated from one method to another:
def inRange(i,j,k):
"""
Returns True if i in [j, k[
* 0 <= i, j, k < MAX
* no order is assumed between j and k: we can have k < j
"""
if j <= k:
return j <= i < k
# j > k :
return j <= i or i < k
def inStrictRange(i,j,k):
"""
Returns True if i in ]j, k[
* 0 <= i, j, k < MAX
* no order is assumed between j and k: we can have k < j
"""
if j <= k:
return j < i < k
# j > k :
return j < i or i < k
def inRange2(i,j,k):
"""
Returns True if i in ]j, k]
* 0 <= i, j, k < MAX
* no order is assumed between j and k: we can have k < j
"""
if j <= k:
return j < i <= k
# j > k :
return j < i or i <= k
Do you know any cleaner way to implement those three methods? After all, only the operators are changing?!
After thinking of a better solution, I came up with:
from operator import lt, le
def _compare(i,j,k, op1, op2):
if j <= k:
return op1(j,i) and op2(i,k)
return op1(j,i) or op2(i,k)
def inRange(i,j,k):
return _compare(i,j,k, le, lt)
def inStrictRange(i,j,k):
return _compare(i,j,k, lt, lt)
def inRange2(i,j,k):
return _compare(i,j,k, lt, le)
Is it any better? Can you come up with something more intuitive? In short, what would be the Pythonic way to write these three operators?
Also, I hate the inRange, inStrictRange, inRange2 names, but I can't think of crystal-clear names. Any ideas?
Thanks.