我需要这样的东西:
>>> for i in mark_last([1, 2, 3]):
... print(i)
...
(1, False)
(2, False)
(3, True)
我是这样实现的,但是......
def mark_last(li):
items = iter(items)
try:
prev = next(items)
except StopIteration:
return
for item in items:
yield prev, False
prev = item
yield prev, True
这是否有内置功能?或者更简短的方法呢?也许与itertools.groupby()
结合的东西? - 不接受具有len()
的技巧,因为它们不适用于生成器。
答案 0 :(得分:2)
您可以使用mark_last
来定义iwindow
,这会返回滑动
可迭代的窗口。
import itertools as IT
def iwindow(iterable, n=2):
"""
Returns a sliding window (of width n) over data from the sequence.
s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...
"""
iterables = IT.tee(iterable, n)
iterables = (IT.islice(it, pos, None) for pos, it in enumerate(iterables))
for result in IT.izip(*iterables):
yield result
def mark_last(iterable):
for i, j in iwindow(iterable):
yield i, False
yield j, True
for i in mark_last([1, 2, 3]):
print(i)
产量
(1, False)
(2, False)
(3, True)
请注意,您可以直接使用iwindow
来解决问题,而不需要mark_last
。
答案 1 :(得分:2)
是否有一些内置标记序列的最后一个?
不,没有。
你的功能很好,除了两点:
raise StopIteration
你应该break
;最终raise StopIteration
会产生RunTimeError
(PEP 479)。答案 2 :(得分:2)
你提供的更简洁的版本是
def mark_last(items):
items = iter(items)
prev = next(items)
for item in items:
yield prev, False
prev = item
yield item, True
请注意,不推荐使用裸next
引发StopIteration
,因此您可能希望使用明确的try...except
。
答案 3 :(得分:0)
在Python 3 +中
对于大型列表,这可能有点难以实现...
>>> def mark_last(iterable):
... *others, last = iterable
... for element in others:
... yield (element, False)
... yield (last, True)
...
>>> for i in mark_last([1, 2, 3]):
... print(i)
...
(1, False)
(2, False)
(3, True)
如果目标列表包含一个前缀为星号的目标, 称为“已加星标”的目标:对象必须至少是一个序列 与目标列表中的目标一样多的项目减去一个。的的 序列的第一项从左到右分配给 在加星标的目标之前的目标。序列的最后一项是 在已加星标的目标后分配给目标。一份清单 然后,序列中的剩余项目将分配给已加星标的目标 (列表可以为空)。
这是在*others, last = iterable
行上完成的,但反之亦然。