生成器在输入迭代器的开始和结束处保留一个占位符 [英] Generator which leaves a placeholder at the beginning and at the end of the input iterator intact

查看:127
本文介绍了生成器在输入迭代器的开始和结束处保留一个占位符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们以一个列表为例:

$ $ $ $ $ $ c $ 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] 并完好保留。



所以,我试图修改生成器来工作out:

Python 2.7

  from __future__ import print_function $ b $ from itertools import tee,izip,ifilterfalse 

def replace(iterable,placeholder = 255):
it = enumerate(可迭代)#需要位置列表中间的逻辑
it = ifilterfalse(lambda x:x [1] ==占位符,它)#创建一个迭代器,删除所有占位符
for i,(left,right)在枚举(window(it,2))中:#通过带有2个元素窗口的过滤列表
if i == 0:#将开始占位符完整
替换为范围内的j(left [ 0]):
产生占位符

#Some中间的逻辑LIST(效果很好)

#需要完整地保留尾随占位符。

将临时值转换为列表以简化对代码的理解:

 >>>迭代式
[255,1,255,255,1,255,255,255,2,2,255,255,255,2,2,3,255,255,255,3,255,255]
$ b $ gt;>> it =枚举(可迭代)
[(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),(

>>> it = ifilterfalse(lambda x:x [1] ==占位符,它)
[(1,1),(4, 1),(8,2),(9,2),(13,2),(14,2),(15,3),(19,3)]

>> ((1,1)),(1,((4,1),(8))列表(枚举(窗口(it,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)))]

因此,您可以看到,列表(枚举(window(it,2)) )包含前导非占位符值的索引(0,((** 1 **,1),(4,1))),,但它不包含这个信息有多少个初始迭代器的尾随占位符: list(enumerate(window(it,2)))以这个值结尾(6,( (15,3),(** 19 **,3))),它只有最后一个非占位符值的索引,它没有给出信息剩下多少个占位符。

我通过依靠 it = enumerate(iterable)来设法处理主要占位符,初始迭代器值,它在第一次产生的值中由 ifilterfalse



保持不变但我花了很多时间尝试弄清楚如何用尾随占位符做同样的事情。问题是, ifilterfalse 只是吞下枚举(iterable)的最后一个占位符值,我看不到它们的访问方式(自从第一次生成的>生成的值包含了枚举值(可迭代)的索引后,前导占位符是可能的

问题



更正的最佳方法是什么此代码为它来处理尾随占位符?



由于目标不是通过一切手段创建代码(我已经),然后使用一种不同的技术来完成它的工作。 ,我想通过修改代码来解决任务,而不是完全重写它。



这不仅仅是一项训练,而是一项真正的任务。



其他信息

window 此处的代码。



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

另外,我希望我的生成器接受任何可迭代的参数,不仅仅是列表(例如它可以接受从文件中逐一读取值的迭代器)。由于只有列表作为参数,任务变得更简单,因为我们可以从最后扫描列表。



这不是我必须在生活中解决的真正任务。这只是一个培训。



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

解决方案

我想出了最简单的解决方案是通过一个生成器来处理 it =枚举(可迭代),它只保存最后返回的值。



<因此,我在 it = enumerate(iterable)(在 replace 函数内)添加了以下代码:

  def save_last(可迭代):
for iterable:
yield i
替换。 last_index = i [0]#保存最后一个值
it = save_last(it)

iterable 用尽之后,生成器的最后一个操作符保存已赋值的索引(即 i [0] as enumerate 将它保存在tupele的位置 0 )作为替换属性(因为替换函数是一个类的实例,它可以有局部变量)。 code> it 包装在新创建的生成器 save_last 中。



在函数的最后,我添加了使用 replace.last_index 变量中已保存索引的代码。

  if right [0]< replace.last_index:
for i in range(replace.last_index-right [0]):
产生占位符

完整的代码:

 from __future__ import print_function $ b $ from itertools import tee,izip,ifilterfalse 


def window(iterable,n):
els = tee(iterable,n)
为我,el为枚举(els):
为_范围(i):
next(el,None)
return izip * els)


def replace(iterable,placeholder = 255):
it =枚举(可迭代)

def save_last(可迭代的):
for i in iterable:
yield i
replace.last_index = i [0]#保存最后一个值
it = save_last(it)

it = ifilterfalse(lambda x:x [1] ==占位符,它)
在枚举(窗口(it,2))中为i,(左,右):
if i = = 0:
为范围内的j(左[0]):
产生占位符
产生剩余[1]
如果正确[0]> left [0] +1 :
if left [1] == right [1]:
for _ in range(right [0] -left [0] -1):
yield left [1]
else:
for _ in range(right [0] -left [0] -1):
产生占位符
产权[1]
if right [0] < replace.last_index:
for i in range(replace.last_index-right [0]):
产生占位符


a = [255,1,255,255,1,255,255,255 ,2,2,255,255,255,2,2,3,255,255,255,3,255,255]
print('\\\
Input:{} .format(a))
output = list(replace(a))
print('Proram output:{}'。format(output))
print('目标输出:{} '.format([255,1,1,1,1,255,255,255,2,2,2,2,2,2,2,3,3,3,3,3,255,255]))
 输入

:[255,1,255,255,1,255,255,255,2,2,25,255,255,2,2,3,255,255,255,3,255,255]
Proram输出:[255,1,1,1,1,25,255,255,2,2,2,2,2,2,2,3,3,3,3,25,255]
目标输出:[255,1,1,1,1,25,255,255,2,2,2,2,2,2,2,3,3,3,3,3,5,25,255]






我唯一不喜欢的是以Python编写的C ifilterfalse save_last 非常高效的组合。


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

解决方案

The simplest solution I came up with is to process it = enumerate(iterable) through one more generator which just saves the last returned value by it.

So, I added the following code after it = enumerate(iterable) (inside the replace function):

def save_last(iterable):
        for i in iterable:
            yield i
        replace.last_index = i[0] #Save the last value
it = save_last(it)

After iterable is exhausted, the last operator of the generator saves the index of the yielded value (which is i[0] as enumerate stores it at the position 0 of tupele) as the replace attribute (since replace function is a instance of a class, which can have local variables).

The it is wrapped in the newly created generator save_last.

At the very end of the function I added the code which uses the saved index in replace.last_index variable.

if right[0]<replace.last_index:
    for i in range(replace.last_index-right[0]):
        yield placeholder

The full code:

from __future__ import print_function
from  itertools import tee, izip, ifilterfalse


def window(iterable,n):
    els = tee(iterable,n)
    for i,el in enumerate(els):
        for _ in range(i):
            next(el, None)
    return izip(*els)


def replace(iterable,placeholder=255):
    it = enumerate(iterable)

    def save_last(iterable):
        for i in iterable:
            yield i
        replace.last_index = i[0] #Save the last value
    it = save_last(it)

    it = ifilterfalse(lambda x: x[1]==placeholder, it)
    for i,(left,right) in enumerate(window(it,2)):
        if i==0:
            for j in range(left[0]):
                yield placeholder
        yield left[1]
        if right[0]>left[0]+1:
            if left[1]==right[1]:
                for _ in range(right[0]-left[0]-1):
                    yield left[1]
            else:
                for _ in range(right[0]-left[0]-1):
                    yield placeholder
    yield right[1]
    if right[0]<replace.last_index:
        for i in range(replace.last_index-right[0]):
            yield placeholder


a = [255,1,255,255,1,255,255,255,2,2,255,255,255,2,2,3,255,255,255,3,255,255]        
print('\nInput: {}'.format(a))
output = list(replace(a))
print('Proram output: {}'.format(output))
print('Goal output  : {}'.format([255,1,1,1,1,255,255,255,2,2,2,2,2,2,2,3,3,3,3,3,255,255]))

Which works as expected:

Input: [255, 1, 255, 255, 1, 255, 255, 255, 2, 2, 255, 255, 255, 2, 2, 3, 255, 255, 255, 3, 255, 255]
Proram output: [255, 1, 1, 1, 1, 255, 255, 255, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 255, 255]
Goal output  : [255, 1, 1, 1, 1, 255, 255, 255, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 255, 255]


The only thing that I don't like is the combination of very efficient written in C ifilterfalse and save_last written in Python.

这篇关于生成器在输入迭代器的开始和结束处保留一个占位符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆