Давайте рассмотрим список в качестве примера:
a = [255, 255, 1, 255, 255, 255, 1, 2, 255, 255, 2, 255, 255, 3, 255, 3, 255, 255, 255]
255
- это особое значение в нем. Это заполнитель.
Я создал генератор, который заменит часть заполнителя в списке. Работает как положено.
Но мне не нужно обрабатывать начальные заполнители [255, 255
и конечные заполнители 255, 255, 255]
и выводить их без изменений.
Итак, я попытался изменить генератор, чтобы он работал:
Python 2.7
from __future__ import print_function
from itertools import tee, izip, ifilterfalse
def replace(iterable,placeholder=255):
it = enumerate(iterable) #the position is needed for the logic for the middle of the list
it = ifilterfalse(lambda x: x[1]==placeholder, it) #create an iterator that deletes all the placeholders
for i,(left,right) in enumerate(window(it,2)): #Slide through the filtered list with the window of 2 elements
if i==0: #Leaving the beginning placeholders intact
for j in range(left[0]):
yield placeholder
#SOME LOGIC FOR THE MIDDLE OF THE LIST (it works well)
#Need to leave the trailing placeholders intact.
Промежуточные значения, преобразованные в список, просто для облегчения понимания кода:
>>>iterable
[255,1,255,255,1,255,255,255,2,2,255,255,255,2,2,3,255,255,255,3,255,255]
>>>it = enumerate(iterable)
[(0, 255), (1, 1), (2, 255), (3, 255), (4, 1), (5, 255), (6, 255), (7, 255), (8, 2), (9, 2), (10, 255), (11, 255), (12, 255), (13, 2), (14, 2), (15, 3), (16, 255), (17, 255), (18, 255), (19, 3), (20, 255), (21, 255)]
>>>it = ifilterfalse(lambda x: x[1]==placeholder, it)
[(1, 1), (4, 1), (8, 2), (9, 2), (13, 2), (14, 2), (15, 3), (19, 3)]
>>>list(enumerate(window(it,2)))
[(0, ((1, 1), (4, 1))), (1, ((4, 1), (8, 2))), (2, ((8, 2), (9, 2))), (3, ((9, 2), (13, 2))), (4, ((13, 2), (14, 2))), (5, ((14, 2), (15, 3))), (6, ((15, 3), (19, 3)))]
Итак, как вы можете видеть, list(enumerate(window(it,2)))
содержит индекс начального значения без заполнителя (0, ((**1**, 1), (4, 1))),
, но не содержит информацию о том, сколько конечных заполнителей было у исходного итератора: list(enumerate(window(it,2)))
заканчивается это значение (6, ((15, 3), (**19**, 3)))
, которое имеет только индекс последнего значения, не являющегося заполнителем, которое не дает информации о количестве оставшихся заполнителей.
Мне удалось обработать ведущие заполнители, полагаясь на it = enumerate(iterable)
, который возвращает позицию начального значения итератора, которое сохраняется в первом полученном значении, на ifilterfalse
.
Но я потратил довольно много времени, пытаясь понять, как сделать то же самое с конечными заполнителями. Проблема в том, что ifilterfalse
просто глотает последние значения заполнителей enumerate(iterable)
, и я не вижу способа получить к ним доступ (это было возможно для ведущих заполнителей, поскольку первое сгенерированное значение ifilterfalse
содержало индекс значения enumerate(iterable)
).
Вопрос
Каков наилучший способ исправить этот код, чтобы он обрабатывал конечные заполнители?
Поскольку цель состоит не в том, чтобы создать код всеми средствами (я уже сделал это , используя другую технику), я хочу решить задачу, немного повозившись с кодом, а не полностью переписать его.
Это больше тренировка, чем реальная задача.
Дополнительная информация
window
- это код от здесь .
Мой код работает почти так же, как в этом ответе @ nye17. Но в этом коде автор вносит на месте изменения исходного списка. И я хочу создать генератор, который будет давать те же значения, что и результирующий список в этом коде.
Кроме того, я хочу, чтобы мой генератор принимал любые итерации в качестве параметра, а не только списки (например, он может принимать итератор, который читает значения из файла одно за другим). Имея только списки в качестве параметра, задача упрощается, поскольку мы можем сканировать список с конца.
Это не настоящая задача, которую мне приходится решать в жизни. Это просто для тренировки.
Полный код
http://codepad.org/9UJ9comY