Common Lisp maplist
函数的最佳Python等价物是什么?来自maplist documentation:
maplist就像mapcar一样 函数应用于连续 列表的子列表。功能是 首先应用于列表本身, 然后到每个列表的cdr,和 然后到每个cdr的cdr 列表,等等。
示例(伪代码,未测试):
>>> def p(x): return x
>>> maplist(p, [1,2,3])
[[1, 2, 3], [2, 3], [3]]
注意:在上面示例中传递给p
的参数将是列表[1, 2, 3]
,[2, 3]
,[3]
;即,p
未应用于这些列表的元素。 E.g:
>>> maplist(lambda l: list(reversed(l)), [1,2,3])
[[3, 2, 1], [3, 2], [3]]
答案 0 :(得分: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]]
<强> [编辑] 强>
如果要在子列表上应用该功能,可以将功能更改为:
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]]
答案 1 :(得分:6)
正如@Cybis和其他人所提到的,你无法保持Python列表的O(N)复杂性;你必须创建一个链表。冒着证明Greenspun's 10th rule的风险,这是一个解决方案:
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
测试产量:
>>> 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]]
编辑:这是一个基于生成器的解决方案,基本上解决了相同的问题,而不使用链接列表:
import itertools
def mapiter(func, iter_):
while True:
iter_, iter2 = itertools.tee(iter_)
iter_.next()
yield func(iter2)
测试产量:
>>> print list(mapiter(lambda l: list(reversed(list(l))), [1,2,3]))
[[3, 2, 1], [3, 2], [3]]
答案 2 :(得分:3)
Eewww ...切片列表是线性时间操作。到目前为止发布的所有解决方案都具有O(n ^ 2)时间复杂度。我相信,Lisp的地图列表有O(n)。
问题是,Python的列表类型不是链表。它是一个动态可调整大小的数组(即,类似于C ++ STL的“向量”类型)。
如果保持线性时间复杂度对您很重要,则无法在Python列表上创建“maplist”函数。最好修改你的代码以使用索引到列表中,或者将列表转换为实际的链表(仍然是线性时间操作,但会有很多开销)。
答案 3 :(得分:1)
这就像你的例子(我修改了reyjavikvi的代码)
def maplist(func, l):
result=[]
for i in range(len(l)):
result.append(func(l[i:]))
return result
答案 4 :(得分:1)
您可以使用嵌套列表推导:
>>> def p(x): return x
>>> l = range(4)[1:]
>>> [p([i:]) for i in range(len(l))]
[[1, 2, 3], [2, 3], [3]]
您可以自己定义地图列表:
>>> def maplist(p, l): return [p([i:]) for i in range(len(l))]
>>> maplist(p, l)
[[1, 2, 3], [2, 3], [3]]
答案 5 :(得分:1)
maplist()
maplist = lambda f, lst: cons(f(lst), maplist(f, cdr(lst))) if lst else lst
请参阅Python Linked List问题。
答案 6 :(得分:1)
Python有一个链表类型,名为deque
:
from collections import deque
def maplist(f, lst):
linked = deque(lst)
results = []
while linked:
results.append(f(linked))
linked.popleft() # assumes left is head, as in lisp
return results
In [134]: maplist(lambda l: list(reversed(l))*2, [1,2,3])
Out[134]: [[3, 2, 1, 3, 2, 1], [3, 2, 3, 2], [3, 3]]
线性时间,同样的事情,将具有与lisp列表上的操作相同的性能特征(即修改内部元素将在被修改的列表的长度中是线性的),以及相同的语义(即,如果{{1修改列表,它会在f
调用中为f
的所有后续执行修改它;但是,因为这会创建maplist
的副本,lst
无法修改{ {1}},与Common Lisp不同。
答案 7 :(得分:0)
修改亚伦的答案:
In [8]: def maplist(p, l): return [p([x for x in l[i:]]) for i in range(len(l))]
...:
In [9]: maplist(lambda x: x + x, [1,2,3])
Out[9]: [[1, 2, 3, 1, 2, 3], [2, 3, 2, 3], [3, 3]]
答案 8 :(得分:-1)
我认为没有,但以下功能可以起作用:
def maplist(func, l):
for i in range(len(l)):
func(l[i:])