python - 在输入迭代器的开头和结尾保留占位符的生成器完好无损

标签 python functional-programming python-itertools

我们以列表为例:

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) 的值的索引)。

问题

更正此代码以使其处理尾随占位符的最佳方法是什么?

由于目标不是一定要创建代码(我已经 done it 使用了不同的技术),所以我想通过对代码进行一些修改来解决这个任务,而不是完全重写它。

与其说是真正的任务,不如说是培训。

附加信息

window 是来自 here 的代码.

我的代码几乎与 this 中的代码相同@nye17 回答。但是在这段代码中,作者对初始列表进行了就地修改。我想创建一个生成器,它将生成与该代码中的结果列表相同的值。

此外,我希望我的生成器接受任何可迭代对象作为参数,而不仅仅是列表(例如,它可以接受从文件中逐个读取值的迭代器)。仅将列表作为参数,任务变得更简单,因为我们可以从末尾扫描列表。

这不是我必须在生活中解决的真正任务。这只是为了训练。

完整代码 http://codepad.org/9UJ9comY

最佳答案

def replace(it, process, placeholder):
    it = iter(it)
    while True:
        item = it.next()
        if item == placeholder:
            yield item
        else:
            yield process(item)
    pcount = 0
    try:
        while True:
            item = it.next()
            if item == placeholder:
                pcount += 1
            else:
                for i in range(pcount):
                    yield process(placeholder)
                pcount = 0
                yield process(item)
    except StopIteration:
        for i in range(pcount):
            yield placeholder

像这样使用它:

>>> a = [0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 2, 0, 0, 3, 0, 3, 0, 0, 0]
>>> [x for x in replace(a, lambda n: n+20, 0)]
[0, 0, 21, 20, 20, 20, 21, 22, 20, 20, 22, 20, 20, 23, 20, 23, 0, 0, 0]

关于python - 在输入迭代器的开头和结尾保留占位符的生成器完好无损,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7755227/

相关文章:

python 2.7 |回车符不起作用

python - 这是如何在 Python 2.7.x 中生成器工作的

clojure - clojure 映射和关键字如何成为一个函数

haskell - 函数参数似乎在类型分析中消失了

python - pandas - 分割字符串并取出每对

python - random.sample(sample,k) 和 itertools.combinations(p,r) 之间的区别

python - 如果我进行一次热编码,我是否总是需要保留一份训练数据的副本?

python - 创建 key :value pair in the first loop and append more values in subsequent loops

Streams 上的startsWith 的Scala 实现

Python:使用 "yield"生成树