Reputation: 2928
Is there a way to get the previous item in a list
, based on 'closeness'? For example:
[ Range(start=datetime.datetime(2012, 1, 1, 0, 0, 0), end=datetime.datetime(2012, 1, 15, 0, 0, 0)),
Range(start=datetime.datetime(2012, 2, 1, 0, 0, 0), end=datetime.datetime(2012, 2, 15, 0, 0, 0)),
Range(start=datetime.datetime(2012, 3, 1, 0, 0, 0), end=datetime.datetime(2012, 3, 15, 0, 0, 0))]
Above is a list
containing namedtuple
s (called Range
), each containing a start date and an end date.
I know that this can be done in a linear way using loops etc., but I was wondering if it could be done more efficiently?
Example input/output:
If I input datetime.datetime(2012, 1, 3, 0, 0, 0)
, it should return the closest previous start datetime:
Range(start=datetime.datetime(2012, 1, 1, 0, 0, 0), end=datetime.datetime(2012, 1, 15, 0, 0, 0))
If I input datetime.datetime(2012, 1, 27, 0, 0, 0)
, it should return the same as above:
Range(start=datetime.datetime(2012, 1, 1, 0, 0, 0), end=datetime.datetime(2012, 1, 15, 0, 0, 0))
If I input datetime.datetime(2012, 2, 14, 0, 0, 0)
, it should return:
Range(start=datetime.datetime(2012, 2, 1, 0, 0, 0), end=datetime.datetime(2012, 2, 15, 0, 0, 0))
Upvotes: 0
Views: 82
Reputation: 57804
If you implement __lt__
or __cmp__
for your Range
object, you can do:
import bisect
position = bisect.bisect_left(range_list, your_input)
if position > 0:
nearest_range = range_list[position - 1]
else:
nearest_range = None
This, of course, assumes that your list is already sorted.
Upvotes: 2
Reputation: 1122142
Sets are by definition not ordered:
A set object is an unordered collection of distinct hashable objects.
You want to use a list or tuple instead, and perhaps make your Range
objects sortable (implement a __cmp__
method, or use an appropriate key function; see the Python sorting HOWTO).
Upvotes: 2