I have a list with periods separated by None
values and I need to create a list of list where each sub-list contains the min and max date for the respective period.
Example:
import datetime
dates = [None, None, datetime.date(2018, 1, 11), datetime.date(2018, 3, 2), datetime.date(2018, 4, 30), datetime.date(2018, 5, 1), None, datetime.date(2018, 5, 30), datetime.date(2018, 6, 3), datetime.date(2018, 6, 4), None, None]
Desired output:
[[datetime.date(2018, 1, 11), datetime.date(2018, 5, 1)],
[datetime.date(2018, 5, 30), datetime.date(2018, 6, 4)]]
How can I do this?
You can use itertools.groupby
( doc ) to group elements to None
and date
values and then use min()
, max()
functions:
import datetime
dates = [None, None, datetime.date(2018, 1, 11), datetime.date(2018, 3, 2), datetime.date(2018, 4, 30), datetime.date(2018, 5, 1), None, datetime.date(2018, 5, 30), datetime.date(2018, 6, 3), datetime.date(2018, 6, 4), None, None]
from itertools import groupby
out = []
for v, g in groupby(dates, lambda k: k is None):
if v:
continue
l = [*g]
out.append([min(l), max(l)])
from pprint import pprint
pprint(out)
Prints:
[[datetime.date(2018, 1, 11), datetime.date(2018, 5, 1)],
[datetime.date(2018, 5, 30), datetime.date(2018, 6, 4)]]
EDIT: Thanks to @BlackJack suggestion, this can be simplified:
out = []
for v, g in groupby(dates, bool):
if v:
l = [*g]
out.append([min(l), max(l)])
Here is my take on it. This solution does not require any additional imports and is logically beginner friendly. Here are the basics of how it works:
You iterate the list ignoring first two and the last None
values.
When you encounter the first value in list or after a None
you set both your min and max to that value as this represents start of new period.
After that, for each value you encounter you compare it to previous min and max and set it as new min or max if lower or higher.
Once you encounter None
you save your current min and max into a list of results and reset them because this means the new period will start with next value.
import datetime
dates = [None, None, datetime.date(2018, 1, 11), datetime.date(2018, 3, 2), datetime.date(2018, 4, 30),
datetime.date(2018, 5, 1), None, datetime.date(2018, 5, 30), datetime.date(2018, 6, 3),
datetime.date(2018, 6, 4), None, None]
min_date = None
max_date = None
result = []
for value in dates[2:-1]:
if value is None:
result.append([min_date, max_date])
min_date = None
max_date = None
elif min_date is None and max_date is None:
min_date = value
max_date = value
elif value < min_date:
min_date = value
elif value > max_date:
max_date = value
print(result)
Output:
[[datetime.date(2018, 1, 11), datetime.date(2018, 5, 1)], [datetime.date(2018, 5, 30), datetime.date(2018, 6, 4)]]
Hope you learned something from this.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.