Let's take a list as an example:
a = [255, 255, 1, 255, 255, 255, 1, 2, 255, 255, 2, 255, 255, 3, 255, 3, 255, 255, 255]
255
is a special value in it. It's a placeholder.
I've made a generator which replaces some of the placeholder inside the list. It works as expected.
But I need not to process the beginning placeholders [255, 255
and the ending placeholders 255, 255, 255]
and yield them intact.
So, I tried to modify the generator to work it out:
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.
The interim values converted to list just to ease the comprehension of the code:
>>>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)))]
So, as you can see, the list(enumerate(window(it,2)))
contains the index of the leading non-placeholder value (0, ((**1**, 1), (4, 1))),
, but it doesn't contain the information how many trailing placeholder the initial iterator had: list(enumerate(window(it,2)))
ends in this value (6, ((15, 3), (**19**, 3)))
which has only the index of the last non-placeholder value, which doesn't give the information how many placeholders are left.
I managed to process the leading placeholders by relying on it = enumerate(iterable)
which yields the position of the initial iterator value which persists in the first yielded value by ifilterfalse
.
But I spent quite a lot of time trying to figure out how to do the same thing with the trailing placeholders. The problem is that ifilterfalse
just swallows the last placeholder values of enumerate(iterable)
and I see no way to access them (it was possible for the leading placeholders since the first generated value of ifilterfalse
contained the index of the value of the enumerate(iterable)
).
Question
What is the best way to correct this code for it to process the trailing placeholders?
As the goal is not to create a code by all means (I have already done it using a different technique), I want to solve the task by tinkering a bit wit the code, not a complete rewriting it.
It's more of a training than a real task.
Additional information
window
is the code from here.
My code does nearly the same as in this answer by @nye17. But in this code the author make inplace modifications of the initial list. And I want to create a generator which will be yielding the same values as the resultant list in that code.
Furthermore, I want my generator to accept any iterables as a parameter, not only lists (for example it may accept the iterator which reads the values from file one by one). With having only lists as a parameter, the task becomes simpler, since we can scan the list from the end.
This is not a real task I have to solve in life. It's just for a training.
Full code http://codepad.org/9UJ9comY