有时我需要遍历列表中的连续对。我现在的做法是
(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 这样的内置函数可以让我得到这个?
有时我需要遍历列表中的连续对。我现在的做法是
(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 这样的内置函数可以让我得到这个?
AFAIK,没有内置功能可以做你想做的事。您可以尝试将某些东西与 放在一起maplist
,但我的第一直觉也是伸手loop
去拿。
不过,只是对您所拥有的内容进行了一些说明。首先,(not (null foo))
等价foo
于 CL,因为非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 作为其结果的最后一个元素,而不是在此之前结束)。
我相信 Paul Graham 在 OnLisp 中有一个名为 map-tuple 的函数来执行此操作。它可以按 cdr、cddr 或任何您喜欢的方式在列表中向下移动。这是它的注释版本。它使用他的照应 if 宏 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)))))