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