我有一个可以包含None
和datetime
对象的列表。我需要在连续的datetime
个对象的子列表中拆分它,并且需要在原始列表中记录该子列表的第一个datetime
对象的索引。
例如,我需要能够转向
original = [None, datetime(2013, 6, 4), datetime(2014, 5, 12), None, None, datetime(2012, 5, 18), None]
成:
(1, [datetime.datetime(2013, 6, 4, 0, 0), datetime.datetime(2014, 5, 12, 0, 0)])
(5, [datetime.datetime(2012, 5, 18, 0, 0)])
我尝试了两种方法。一个使用find
:
binary = ''.join('1' if d else '0' for d in original)
end = 0
start = binary.find('1', end)
while start > -1:
end = binary.find('0', start)
if end < 0:
end = len(binary)
dates = original[start:end]
print (start, dates)
start = binary.find('1', end)
和一个使用groupby
:
from itertools import groupby
for key, group in groupby(enumerate(original), lambda x: x[1] is not None):
if key:
group = list(group)
start = group[0][0]
dates = [t[1] for t in group]
print (start, dates)
但两者对我来说似乎并不过分Pythonic。还有更好的方法吗?
答案 0 :(得分:7)
我使用生成器生成元素,封装分组:
from itertools import takewhile
def indexed_date_groups(it):
indexed = enumerate(it)
for i, elem in indexed:
if elem is not None:
yield (
i, [elem] + [v for i, v in takewhile(
lambda v: v[1] is not None, indexed)])
我们在找到初始非 - None
对象后,使用itertools.takewhile()
生成子列表。
当然,您仍然可以使用itertools.groupby()
执行相同操作:
from itertools import groupby
def indexed_date_groups(it):
for key, group in groupby(enumerate(it), lambda v: v[1] is not None):
if key:
indices, elems = zip(*group)
yield indices[0], elems
演示:
>>> list(indexed_date_groups(original))
[(1, [datetime.datetime(2013, 6, 4, 0, 0), datetime.datetime(2014, 5, 12, 0, 0)]), (5, [datetime.datetime(2012, 5, 18, 0, 0)])]
>>> original = [None, datetime(2013, 6, 4), datetime(2014, 5, 12), None, None, datetime(2012, 5, 18), None]
>>> for index, group in indexed_date_groups(original):
... print index, group
...
1 [datetime.datetime(2013, 6, 4, 0, 0), datetime.datetime(2014, 5, 12, 0, 0)]
5 [datetime.datetime(2012, 5, 18, 0, 0)]
答案 1 :(得分:3)
from itertools import groupby, count
idx = count()
for key, group in groupby(original, lambda x: x is not None):
indices, group = zip(*((next(idx), i) for i in group))
if key:
print (indices[0], group)
答案 2 :(得分:2)
基于gnibbler's answer。它省去count
和zip
并直接计算索引:
from itertools import groupby
idx = 0
for key, group in groupby(original, lambda x: x is not None):
group = list(group)
if key:
print idx, group
idx += len(group)