11 апреля 2013 г.

Создание собственных версий функций zip(...) и map(None, ...)


В предыдущих постах мы создавали якобы свои функции zip и map . Но это не совсем то, что нам нужно, так как создавая одну из них мы использовали вторую - которая встроена в язык программирования Python.

Поэтому в этом посте мы это полностью исправим. Кстати в разных версиях, map работает по разному, вот некоторые примеры для Python 2.x и Python 3.0.


C:\misc> c:\python26\python
>>> map(None, [1, 2, 3], [2, 3, 4, 5])
[(1, 2), (2, 3), (3, 4), (None, 5)]
>>> map(None, ‘abc’, ‘xyz123’)
[(‘a’, ‘x’), (‘b’, ‘y’), (‘c’, ‘z’), (None, ‘1’), (None, ‘2’), (None, ‘3’)]


Используя инструменты итераций, мы можем создать версии, имитирующие усечение, как это делает функция zip, и дополнение, как это делает функция map в версии 2.6. Как оказывается, эти версии почти не отличаются от предыдущих:


# Версии zip(seqs...) и map(None, seqs...) в Python 2.6 
def myzip(*seqs):
    seqs = [list(S) for S in seqs]
    res = []
    while all(seqs):
        res.append(tuple(S.pop(0) for S in seqs))
    return res

def mymapPad(*seqs, pad=None):
    seqs = [list(S) for S in seqs]
    res = []
    while any(seqs):
        res.append(tuple((S.pop(0) if S else pad) for S in seqs))
    return res

S1, S2 = ‘abc’, ‘xyz123’
print(myzip(S1, S2))
print(mymapPad(S1, S2))
print(mymapPad(S1, S2, pad=99))


Обе функции, представленные здесь, способны работать с любыми итерируемыми объектами, потому что они применяют к своим аргументам встроенную функцию list, вынуждая их сгенерировать все результаты.


# С использованием генераторов: yield 
def myzip(*seqs):
    seqs = [list(S) for S in seqs]
    while all(seqs):
        yield tuple(S.pop(0) for S in seqs)

def mymapPad(*seqs, pad=None):
    seqs = [list(S) for S in seqs]
    while any(seqs):
        yield tuple((S.pop(0) if S else pad) for S in seqs)

S1, S2 = ‘abc’, ‘xyz123’
print(list(myzip(S1, S2)))
print(list(mymapPad(S1, S2)))
print(list(mymapPad(S1, S2, pad=99)))
-----------------------------------------------------------------

# Альтернативные реализации с вычислением длин исходных последовательностей 
def myzip(*seqs):
    minlen = min(len(S) for S in seqs)
    return [tuple(S[i] for S in seqs) for i in range(minlen)]

def mymapPad(*seqs, pad=None):
    maxlen = max(len(S) for S in seqs)
    index = range(maxlen)
    return [tuple((S[i] if len(S) > i else pad) for S in seqs) for i in index]

S1, S2 = ‘abc’, ‘xyz123’
print(myzip(S1, S2))
print(mymapPad(S1, S2))



print(mymapPad(S1, S2, pad=99))

На этом, наш короткий пост - закончился.


Комментариев нет:

Отправить комментарий