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)
正如@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)