Python相当于maplist?

Jac*_*son 11 lisp python functional-programming

什么是最好的Python相当于Common Lisp的maplist功能?从地图列表文档:

maplist与mapcar类似,不同之处在于该函数应用于列表的连续子列表.函数首先应用于列表本身,然后应用于每个列表的cdr,然后应用于每个列表的cdr的cdr,依此类推.

示例(伪代码,未测试):

>>> def p(x): return x
>>> maplist(p, [1,2,3])
[[1, 2, 3], [2, 3], [3]]
Run Code Online (Sandbox Code Playgroud)

:传递给的参数p在上面的例子中会列表[1, 2, 3],[2, 3],[3],即,p不适用于这些列表的元素.例如:

>>> maplist(lambda l: list(reversed(l)), [1,2,3])
[[3, 2, 1], [3, 2], [3]]
Run Code Online (Sandbox Code Playgroud)

Nad*_*mli 11

你可以为它写一点功能

def maplist(func, values):
    return [map(func, values[i:]) for i in xrange(len(values))]

>>> maplist(lambda a: a* 2, [1,2,3])
[[2, 4, 6], [4, 6], [6]]
Run Code Online (Sandbox Code Playgroud)

[编辑]

如果要在子列表上应用该功能,可以将功能更改为:

def maplist(func, values):
    return [func(values[i:]) for i in xrange(len(values))]

>>> maplist(lambda l: list(reversed(l)), [1,2,3])
[[3, 2, 1], [3, 2], [3]]
Run Code Online (Sandbox Code Playgroud)


Ric*_*and 6

正如@Cybis和其他人所提到的,你无法保持Python列表的O(N)复杂性; 你必须创建一个链表.冒着证明格林普森第10条规则的风险,这是一个解决方案:

class cons(tuple):
    __slots__=()

    def __new__(cls, car, cdr):
        return tuple.__new__(cls, (car,cdr))

    @classmethod
    def from_seq(class_, l):
        result = None
        for el in reversed(l):
            result = cons(el, result)
        return result

    @property
    def car(self): return self._getitem(0)

    @property
    def cdr(self): return self._getitem(1)

    def _getitem(self, i):
        return tuple.__getitem__(self, i)

    def __repr__(self):
        return '(%s %r)' % (self.car, self.cdr)

    def __iter__(self):
        v = self
        while v is not None:
            yield v.car
            v = v.cdr

    def __len__(self):
        return sum(1 for x in self)

    def __getitem__(self, i):
        v = self
        while i > 0:
            v = v.cdr
            i -= 1
        return v.car

def maplist(func, values):
    result = [ ]
    while values is not None:
        result.append(func(values))
        values = values.cdr
    return result
Run Code Online (Sandbox Code Playgroud)

测试产量:

>>> l = cons.from_seq([1,2,3,4])
>>> print l
(1 (2 (3 (4 None))))
>>> print list(l)
[1, 2, 3, 4]
>>> print maplistr(lambda l: list(reversed(l)), cons.from_seq([1,2,3]))
[[3, 2, 1], [3, 2], [3]]
Run Code Online (Sandbox Code Playgroud)

编辑:这是一个基于生成器的解决方案,基本上解决了相同的问题,而不使用链接列表:

import itertools

def mapiter(func, iter_):
    while True:
        iter_, iter2 = itertools.tee(iter_)
        iter_.next()
        yield func(iter2)
Run Code Online (Sandbox Code Playgroud)

测试产量:

>>> print list(mapiter(lambda l: list(reversed(list(l))), [1,2,3]))
[[3, 2, 1], [3, 2], [3]]
Run Code Online (Sandbox Code Playgroud)

  • +1表示甚至Python都无法逃脱格林斯普的第10条规则. (2认同)