chdecultot
chdecultot

Reputation: 73

Compare time slots in python

I have the following list of time slots(start_date, end_date), sorted by start date:

slots = [(datetime.datetime(2017, 10, 2, 6, 0), datetime.datetime(2017, 10, 2, 17, 40)), 
(datetime.datetime(2017, 10, 2, 10, 35), datetime.datetime(2017, 10, 2, 16, 25)), 
(datetime.datetime(2017, 10, 2, 11, 0), datetime.datetime(2017, 10, 2, 12, 0)), 
(datetime.datetime(2017, 10, 2, 12, 0), datetime.datetime(2017, 10, 2, 13, 0)), 
(datetime.datetime(2017, 10, 2, 15, 0), datetime.datetime(2017, 10, 2, 16, 0)),
(datetime.datetime(2017, 10, 2, 18, 0), datetime.datetime(2017, 10, 2, 19, 0))]

I would like to remove all timeslots with a start date and an end date included in another timeslot present this list.

So here, for example, the end result should be:

slots = [(datetime.datetime(2017, 10, 2, 6, 0), datetime.datetime(2017, 10, 2, 17, 40)),
(datetime.datetime(2017, 10, 2, 18, 0), datetime.datetime(2017, 10, 2, 19, 0))]

I have tried to reduce it with the following function, but it doesn't work:

reduce(slots_removal, slots)

def slots_removal(a, b):
    if a[1] > b[1]:
        del b

This produces:

TypeError: 'NoneType' object has no attribute '__getitem__'"

Upvotes: 1

Views: 754

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121914

If your input is always sorted, you could just use a generator function:

import datetime

def reduced(timeseries):
    prev = datetime.datetime.min
    for start, end in timeseries:
        if end > prev:
            prev = end
            yield start, end

This only yields (start, end) tuples if end is later than the previousy yielded tuple.

Demo:

>>> list(reduced(slots))
[(datetime.datetime(2017, 10, 2, 6, 0), datetime.datetime(2017, 10, 2, 17, 40)), (datetime.datetime(2017, 10, 2, 18, 0), datetime.datetime(2017, 10, 2, 19, 0))]
>>> from pprint import pprint
>>> pprint(_)
[(datetime.datetime(2017, 10, 2, 6, 0),
  datetime.datetime(2017, 10, 2, 17, 40)),
 (datetime.datetime(2017, 10, 2, 18, 0),
  datetime.datetime(2017, 10, 2, 19, 0))]

You can't use reduce(); that function produces a single result from an input sequence. The output of the function becomes the input for the next call (together with the next element); because your function doesn't explicitl return anything, None is returned instead and used as input for the next call.

Upvotes: 1

Related Questions