简体   繁体   中英

How to create list of lists with min and max date from larger list?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM