I want to be able to apply different transformations to the first and last 
elements of an arbitrary sized finite iterator in python3. It's a custom 
iterator so does not have _reversed_. If the first and last elements are the 
same (e.g. size 1), it should apply both transforms to the same element. I'm 
doing this because I have an iterator of time span tuples, and I want to clamp 
the first and last elements, but know any/all of the middle values are 
inherently in range.

A silly example might be a process that given an iterator of strings, chops the 
the outer characters off of the value, and uppercases the final value. For 
example:


def iterEmpty():
    return iter([])

def iter1():
    yield "howdy"

def iter2():
    yield "howdy"
    yield "byebye"

def iterMany():
    yield "howdy"
    yield "hope"
    yield "your"
    yield "day"
    yield "is"
    yield "swell"
    yield "byebye"

def mapFirst(stream, transform):
    try:
        first = next(stream)
    except StopIteration:
        return
    yield transform(first)
    yield from stream

def mapLast(stream, transform):
    try:
        previous = next(stream)
    except StopIteration:
        return
    for item in stream:
        yield previous
        previous = item
    yield transform(previous)

def main():
    for each in (iterEmpty, iter1, iter2, iterMany):
        baseIterator = each()
        chopFirst = mapFirst(baseIterator, lambda x: x[1:-1])
        andCapLast = mapLast(chopFirst, lambda x: x.upper())
        print(repr(" ".join(andCapLast)))


This outputs:

''
'OWD'
'owd BYEBYE'
'owd hope your day is swell BYEBYE'

Is this idiomatic? Especially my implementations of mapFirst and mapList there 
in the middle? Or is there some way to pull this off that is more elegant?

I've been doing more with iterators and stacking them (probably because I've 
been playing with Elixir elsewhere), I am generally curious what the 
performance tradeoffs of heavy use of iterators and yield functions in python 
is. I know the argument for avoiding big list copies when moving between 
stages. Is it one of those things where there's also some overhead with them, 
where for small stuff, you'd just be better list-ifying the first iterator and 
then working with lists (where, for example, I could do the first/last clamp 
operation with just indexing operations).
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to