Help: Quick way to test if value lies within a list of lists of ranges?

Paddy paddy3118 at netscape.net
Thu Oct 27 18:51:07 EDT 2005


Would this help?


'''
>>> pp(name2ranges)
{'a': [[5, 12], [27, 89], [120, 137]],
 'b': [[6, 23], [26, 84], [200, 222]],
 'c': [[2, 22], [47, 60], [67, 122]]}
>>> names4val(28)
['a', 'b']
>>> names4val(11)
['a', 'c', 'b']
>>> names4val(145)
[]
>>>

'''
from pprint import pprint as pp

name2ranges = {
  'a': [[48,60], [27,89], [5,12], [120,137]],
  'b': [[78,84], [26,79], [200,222], [6,23], [72,74]],
  'c': [[67,122],[2,22], [47,60]]
  }

for name, ranges in name2ranges.iteritems():
  # sort ranges
  name2ranges[name].sort()
  # Coalesce overlapping ranges.
  # If the max of one range is >= the min of the next range then
  # the adjacent ranges are combined
  ln = len(ranges)
  newranges = []
  i = 0
  while i< ln:
    mn,mx = ranges[i]
    j = i+1
    while j< ln and ranges[j][0] <=mx:
      mx = max(mx, ranges[j][1])
      j += 1
    newranges.append([mn,mx])
    i = j
  name2ranges[name] = newranges

def names4val(val):
  " find the names whose ranges intersect the value"
  from bisect import bisect_left
  names = []
  for name,ranges in name2ranges.iteritems():
    bs = bisect_left(ranges, [val,val])
    if (bs and ranges[bs-1][0] <= val <= ranges[bs-1][1] ) or (
        bs <len(ranges) and ranges[bs][0] <= val <= ranges[bs][1] ):
      names.append(name)
  names.sort()
  return names
              
####

Cheers, Pad.




More information about the Python-list mailing list