Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Round to next predefined integer in list

Tags:

python

I have a Python list of predefined integers:

intvals = [5000, 7500, 10000, 20000, 30000, 40000, 50000]

I need to round down and up to the next lower/higher value in the list. So for example, given the number 8000, the result should be [7500, 10000]. For 42000, it should be [40000, 50000]. I am wondering if there is an easy way to do it.

My idea would be to create a function that has two loops - one that decreases a value -1 until it finds one in the list, and one that increases the value by 1 until it finds the higher match. This would work but maybe there is a better solution?

like image 690
Daniel Avatar asked Mar 26 '12 08:03

Daniel


3 Answers

This is perfect for bisect.bisect_right() and bisect.bisect_left().

Here is some example code for which you can expand on:

import bisect

def get_interval(x):
    intvals = [5000, 7500, 10000, 20000, 30000, 40000, 50000]
    i = bisect.bisect_right(intvals,x)
    return intvals[i-1:i+1]

print get_interval(5500)

"""
>>>
[5000, 7500]
"""

This technique is fast as it uses binary search (so logN instead of N lookups)

like image 106
robert king Avatar answered Oct 05 '22 23:10

robert king


You can use the bisect module. You may have to tweak the example to satisfy your boundary case needs.

>>> import bisect
>>> def RoundUpDown(rangeList,num):
    beg = bisect.bisect_right(rangeList,num)
    if rangeList[beg-1] == num: #Handle Perfect Hit Edge Case
        return [num,num]
    elif not beg: #Left Edge Case
        return [None,rangeList[0]]
    elif beg == len(rangeList): #Right Edge Case
        return [rangeList[-1],None]
    else:
        return rangeList[beg-1:beg+1]


>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],41000)
[40000, 50000]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],5000)
[5000, 5000]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],500)
[None, 5000]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],50000)
[50000, 50000]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],51000)
[50000, None]
>>> RoundUpDown([5000, 7500, 10000, 20000, 30000, 40000, 50000],7500)
[7500, 7500]
>>> 
like image 29
Abhijit Avatar answered Oct 05 '22 23:10

Abhijit


bisect is built for searching like this.

>>> intvals[bisect.bisect(intvals, 8000)]
10000
>>> intvals[bisect.bisect(intvals, 42000)]
50000
like image 22
Ignacio Vazquez-Abrams Avatar answered Oct 05 '22 23:10

Ignacio Vazquez-Abrams