Я все думаю, что для этого должна быть функция, но я поискал подходящие места (google, itertools docs, методы списков, другие вопросы SO), но нигде не нашел достаточно чего Я искал.
Наивная и рабочая реализация:
def split_at_first_false(pred, seq):
first = []
second = []
true_so_far = True
for item in seq:
if true_so_far and pred(item):
first.append(item)
else:
true_so_far = False
second.append(item)
return first, second
print split_at_first_false(str.isalpha, "abc1a2b")
# (['a', 'b', 'c'], ['1', 'a', '2', 'b'])
Это работает, но кажется неправильным. Должен быть лучший способ сделать это!
РЕДАКТИРОВАТЬ: Я закончил с использованием немного измененной версии последнего предложения senderle после просмотра ответов:
from itertools import chain
def split_at_pred(pred, seq):
head = []
it = iter(seq)
for i in it:
if not pred(i):
head.append(i)
else:
return iter(head), chain([i], it)
return iter(head), iter([])
Это коротко и элегантно, вывод - два итератора, независимо от того, не имеет значения ввод (строки, списки, итераторы), и в качестве бонуса он даже работает со следующим вводом:
from itertools import count
split_at_pred(lambda x: x == 5, count())
У других решений, которые вообще работают с итераторами, с этим вводом не хватит памяти. (Обратите внимание, что это - это просто бонус. Я даже не думал о бесконечных итераторах, когда писал этот вопрос)