Reputation: 13
Given a list of datetimes:
A= [datetime.datetime(2019, 12, 14, 0, 0), datetime.datetime(2019, 12, 16, 0, 0),
datetime.datetime(2019, 12, 24, 0, 0), datetime.datetime(2019, 12, 25, 0, 0),
datetime.datetime(2019, 12, 26, 0, 0), datetime.datetime(2019, 12, 27, 0, 0),
]
I want to group datetimes whose difference is 1 day so that the output is :
[datetime.datetime(2019, 12, 14, 0, 0),
datetime.datetime(2019, 12, 16, 0, 0),
[datetime.datetime(2019, 12, 24, 0, 0), datetime.datetime(2019, 12, 25, 0, 0),
datetime.datetime(2019, 12, 26, 0, 0), datetime.datetime(2019, 12, 27, 0, 0)]]
I have tried this, but it is failing:
res = []
temp = []
l = len(A)-1
for i,v in enumerate(A):
if i+1 > l:
break
if abs(v.days() - A[i+1].days()) == 1:
temp.append(v)
else:
if temp:
temp.append(v)
res.append(temp)
temp = []
print(res)
Upvotes: 1
Views: 57
Reputation: 24231
The first version of the question was about integers, so here is the answer to "grouping integers whose difference is 1" first (see below for datetime objects).
You can use itertools.groupby and itertools.count to group them like this:
from itertools import groupby, count
counter = count()
A= [1,14,24,25,26,27,28,29,30,31]
out = [list(group) for _, group in groupby(A, key=lambda v:v-next(counter))]
print(out)
# [[1], [14], [24, 25, 26, 27, 28, 29, 30, 31]]
If you really want the isolated values to appear out of any list, just add:
out = [sublist[0] if len(sublist)==1 else sublist for sublist in out]
print(out)
[1, 14, [24, 25, 26, 27, 28, 29, 30, 31]]
next(counter)
will return 0, 1, 2... and so on every time it is called. If the difference between values is 1, v-next(counter)
will be constant, and groupby groups the items for which this remains constant.
For the second version of the question, we can keep the same principle for datetime
objects with one day difference: we subtract a datetime.timedelta(days=next(counter))
instead of just next(counter)
.
from itertools import groupby, count
import datetime
A= [datetime.datetime(2019, 12, 14, 0, 0), datetime.datetime(2019, 12, 16, 0, 0),
datetime.datetime(2019, 12, 24, 0, 0), datetime.datetime(2019, 12, 25, 0, 0),
datetime.datetime(2019, 12, 26, 0, 0), datetime.datetime(2019, 12, 27, 0, 0),
]
counter = count()
out = [list(group) for _, group in groupby(A, key=lambda v:v-datetime.timedelta(days=next(counter)))]
# print(out)
# [1], [14], [24, 25, 26, 27, 28, 29, 30, 31]]
out = [sublist[0] if len(sublist)==1 else sublist for sublist in out]
print(out)
# [datetime.datetime(2019, 12, 14, 0, 0), datetime.datetime(2019, 12, 16, 0, 0),
# [datetime.datetime(2019, 12, 24, 0, 0), datetime.datetime(2019, 12, 25, 0, 0),
# datetime.datetime(2019, 12, 26, 0, 0), datetime.datetime(2019, 12, 27, 0, 0)]]
Upvotes: 5