假设我有一个类似的序列:
seq = (1, 1, 1, 1, 4, 6, 8, 4, 3, 3, 3,)
一些任意数量的1,后跟一些任意数量的偶数,然后是3s。如果我试着把它分开:
it = iter(seq)
ones = list(takewhile(lambda x: x == 1, it))
evens = list(takewhile(lambda x: x%2 == 0, it))
threes = list(takewhile(lambda x: x == 3, it))
这个几乎可以解决...除了我错过了第一个偶数和前三个,因为它已经被takewhile
用完了。有没有办法通过向前走迭代器,谓词谓词来进行这种分区?
答案 0 :(得分:1)
你可以这样做:
def multi_takewhile(predicates, iterable):
ipredicates = iter(predicates)
predicate = next(ipredicates)
last_chunk = []
for element in iterable:
while not predicate(element):
yield last_chunk
last_chunk = []
try:
predicate = next(ipredicates)
except StopIteration:
break
last_chunk.append(element)
但是,如果你的谓词用完了,它仍会遇到消耗最后一个元素的问题。您可以修改函数以返回另一个列表中的最后一个元素,或者创建自己的可迭代包装器,以跟踪最后一个元素。
另一种更itertools
方法可能是groupby
:
import itertools
class Grouper(object):
def __init__(self, predicates):
self.predicates = iter(predicates)
self.predicate = next(self.predicates)
self.key = 0
def __call__(self, element):
if not self.predicate(element):
self.key += 1
self.predicate = next(self.predicates)
return self.key
def multi_takewhile(predicates, iterable):
for _, group in itertools.groupby(iterable, Grouper(predicates)):
yield tuple(group)
seq = [1, 1, 1, 1, 4, 6, 8, 4, 3, 3, 3]
ones, evens, threes = multi_takewhile([(lambda x: x == 1), (lambda x: x%2 == 0), (lambda x: x == 3)], seq)
答案 1 :(得分:1)
groupby
可以在这里使用精心设计的关键函数来处理任意关键函数:
def f1(x): return x == 1
def f2(x): return x%2 == 0
def f3(x): return x == 3
fs = [f1, f2, f3]
def keyfunc(x): return next((f for f in fs if f(x)), None)
for k, vals in itertools.groupby(data, keyfunc):
assert k in {f1, f2, f3, None}
print k, vals
这显然有时会创建重复的分区,例如[1, 1, 3, 1, 3]
答案 2 :(得分:0)
您的示例可由0.704
处理:
groupby