是否有一些内置标记序列的最后一个?
Is there some built-in which marks the last of a sequence?
我需要这样的东西:
>>> 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()
的技巧,因为它们不适用于生成器。
您可以根据 iwindow
定义 mark_last
,其中 returns 滑动
window 在可迭代对象上。
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
。
在Python3+
这对于大型列表的性能可能有点困难...
>>> 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)
If the target list contains one target prefixed with an asterisk,
called a “starred” target: The object must be a sequence with at least
as many items as there are targets in the target list, minus one. The
first items of the sequence are assigned, from left to right, to the
targets before the starred target. The final items of the sequence are
assigned to the targets after the starred target. A list of the
remaining items in the sequence is then assigned to the starred target
(the list can be empty).
这就是 *others, last = iterable
行正在做的事情,但反过来。
Is there some built-in which marks the last of a sequence?
没有,没有。
除了两点,你的功能还不错:
- 它如何处理空序列?
- 你应该
break
而不是 raise StopIteration
;最终 raise StopIteration
将导致 RunTimeError
(PEP 479).
你给出的更简洁的版本是
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
.
我需要这样的东西:
>>> 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()
的技巧,因为它们不适用于生成器。
您可以根据 iwindow
定义 mark_last
,其中 returns 滑动
window 在可迭代对象上。
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
。
在Python3+
这对于大型列表的性能可能有点困难...
>>> 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)
If the target list contains one target prefixed with an asterisk, called a “starred” target: The object must be a sequence with at least as many items as there are targets in the target list, minus one. The first items of the sequence are assigned, from left to right, to the targets before the starred target. The final items of the sequence are assigned to the targets after the starred target. A list of the remaining items in the sequence is then assigned to the starred target (the list can be empty).
这就是 *others, last = iterable
行正在做的事情,但反过来。
Is there some built-in which marks the last of a sequence?
没有,没有。
除了两点,你的功能还不错:
- 它如何处理空序列?
- 你应该
break
而不是raise StopIteration
;最终raise StopIteration
将导致RunTimeError
(PEP 479).
你给出的更简洁的版本是
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
.