«Базовое» решение приведено ниже. Решения, использующие прямое переключение, обращают ввод, и в некоторых случаях это может быть дорогостоящим.
Приведенное ниже решение вычисляет индикаторы начала и конца и возвращает срез ввода.
Это решение работает для других типов последовательностей, таких как кортеж, в которых возвращаемое значение того же типа, что и входные. Этот метод работает и для строковых входов, хотя str.split()
, вероятно, будет быстрее.
def strip_basic(input_data, predicate):
N = len(input_data)
if not N:
return input_data[0:0] # empty sequence, new copy for mutables
i = 0
while i < N and predicate(input_data[i]):
i = i + 1
if i == N: # optimization
return input_data[0:0] # empty sequence
j = N - 1
while j and predicate(input_data[j]):
j = j - 1
j = j + 1
return input_data[i:j]
Для сравнения (в этом решении часть ввода переворачивается дважды):
def strip_dropwhile(input_data, predicate):
return list(dropwhile(predicate, list(dropwhile(predicate, input_data))[::-1]))[::-1]
Вот некоторые числа, использующие timeit
. Обратите внимание, что для патологического случая, когда вход большой и нет элементов для
В отличие от базового решения, выпадающее решение примерно в 8 раз медленнее.
В случае, когда вход большой и все элементы удалены, основное решение заключается в
В 1,9 раза медленнее, чем выпадающее решение.
# input len = 12, output len = 7
# predicate = lambda x: x == '0'; input_data = list('001100101000')
# dropwhile solution:
200000 loops, best of 5: 1.84 usec per loop
# basic solution:
200000 loops, best of 5: 1.51 usec per loop
# input len = 1,000,000, output len = 1,000,000
# predicate = lambda x: x == '0'; input_data = ['1'] * 1000000
# dropwhile solution:
10 loops, best of 5: 29.3 msec per loop
# basic solution:
100 loops, best of 5: 3.58 msec per loop
# input len = 1,000,000, output len = 0
# predicate = lambda x: x == '0'; input_data = ['0'] * 1000000
# dropwhile solution:
5 loops, best of 5: 98 msec per loop
# basic solution:
2 loops, best of 5: 183 msec per loop