有时我需要遍历列表中的连续对。我现在这样做的方式是
(loop for x on lst while (not (null (cdr x)))
(do something on (car x) and (cadr x)))
我想知道是否有更好/内置的方法来做到这一点。
我需要这个的原因有时是我想要的,例如一些添加连续对的函数
(1 2 3 4 5) ----> (3 5 7 9)
是否有像reduce那样的内置函数可以让我得到它?
答案 0 :(得分:7)
AFAIK,没有内置功能可以做你想要的。您可以尝试将某些内容与maplist
放在一起,但我的第一直觉也是loop
。
关于你到底在那里的几个笔记。首先,(not (null foo))
相当于CL中的foo
,因为非NIL
值被布尔运算视为t
。其次,loop
可以解构其论点,这意味着你可以更优雅地写这个
(loop for (a b) on lst while b
collect (+ a b))
maplist
版本看起来像
(maplist
(lambda (rest)
(when (cdr rest)
(+ (first rest) (second rest)))
lst)
我认为它的可读性较低(这也会将NIL作为其结果的最后一个元素返回,而不是在此之前结束)。
答案 1 :(得分:3)
我相信Paul Graham在OnLisp中有一个名为map-tuple的函数来执行此操作。它可以通过cdr,cddr在列表中向下移动,或者不管你喜欢。这是它的评论版本。如果宏 aif ,它会使用他的照应。
(defun map-tuple (someList f &optional (by #'cdr))
"(map-tuple someList f &optional (by #'cdr))
f is a function that takes two args, returns one val (maybe)
the map-tuple will collect all non-nil results in a list.
example:
(map-tuple '(1 2 3 4 5 6) (lambda (a b) (format T \"a: ~A b:~A~%\" a b)) #'cdr)
a: 1 b:2
a: 2 b:3
a: 3 b:4
a: 4 b:5
a: 5 b:6
a: 6 b:NIL
(map-tuple '(1 2 3 4 5 6) (lambda (a b) (format T \"a: ~A b:~A~%\" a b)) #'cddr)
a: 1 b:2
a: 3 b:4
a: 5 b:6
"
(cond ((null someList)
nil)
(T
(aif (funcall f (car someList) (cadr someList))
(cons it (map-tuple (funcall by someList) f by))
(map-tuple (funcall by someList) f by)))))