Common Lisp - 将函数应用于列表中的每个其他元素
Common Lisp - apply function to every other element in list
我想使用 loop 宏将函数 (* x 2) 应用到列表中的每个其他元素和 return 整个列表。到目前为止我想出的解决方案是:
(defun double-every-other (xs)
(loop for x in xs by #'cddr collect (* x 2)))
然而,这将使所有其他元素加倍,并且只有 return 加倍的元素,所以如果我执行:
(double-every-other '(1 2 3 4))
结果将是:
'(4 8)
但我希望结果是:
'(1 4 3 8)
有没有办法使用(循环)来做到这一点?
例如,您可以在扫描列表时测试一个递增的整数:
(defun double-every-other (xs)
(loop for x in xs
for i from 1
if (oddp i)
collect x
else collect (* x 2)))
数学较少的另一个版本:
(defun double-every-other (list)
(loop
for (a b) on list by #'cddr
collect a
when b collect (* b 2)))
(double-every-other '(1 2 3 4))
=> (1 4 3 8)
(double-every-other '(1 2 3 4 5))
=> (1 4 3 8 5)
显然,您无法像其他答案那样轻松地抽象出 N(如果您正在考虑 "macro",请立即停止)。这里我们使用 on
关键字进行迭代,这意味着依次访问每个子列表。由于我们使用 by #'cddr
,所有其他子列表都被跳过。解构语法 (a b)
绑定访问列表的第一个和第二个元素。
(defun double-every-other (xs)
(loop for x in xs
for doublep = nil then (not doublep)
collect (if doublep (* x 2) x)))
另一个版本,完全没有循环:
(defun make-cycled (&rest items)
(setf (cdr (last items)) items))
(mapcar #'funcall
(make-cycled #'identity (lambda (x) (* 2 x)))
'(10 9 8 7 6 5 4 3))
;;=> (10 18 8 14 6 10 4 6)
您可以使用 loop
"on" 列表迭代原语。这需要一个循环变量列表,这些变量将 "smeared" 遍历整个列表,最后一个是整个剩余列表的尾部。如果我们有奇数个参数,则有条件的 loop
是避免乘法 nil
所必需的。
(defun double-every-other (list)
(loop for (single double tail) on list by #'cddr
if (null double)
collect single
else
append (list single (* 2 double))))
如果我们尝试 运行 它:
* (double-every-other '(1 2 3 4 5))
(1 4 3 8 5)
我想使用 loop 宏将函数 (* x 2) 应用到列表中的每个其他元素和 return 整个列表。到目前为止我想出的解决方案是:
(defun double-every-other (xs)
(loop for x in xs by #'cddr collect (* x 2)))
然而,这将使所有其他元素加倍,并且只有 return 加倍的元素,所以如果我执行:
(double-every-other '(1 2 3 4))
结果将是:
'(4 8)
但我希望结果是:
'(1 4 3 8)
有没有办法使用(循环)来做到这一点?
例如,您可以在扫描列表时测试一个递增的整数:
(defun double-every-other (xs)
(loop for x in xs
for i from 1
if (oddp i)
collect x
else collect (* x 2)))
数学较少的另一个版本:
(defun double-every-other (list)
(loop
for (a b) on list by #'cddr
collect a
when b collect (* b 2)))
(double-every-other '(1 2 3 4))
=> (1 4 3 8)
(double-every-other '(1 2 3 4 5))
=> (1 4 3 8 5)
显然,您无法像其他答案那样轻松地抽象出 N(如果您正在考虑 "macro",请立即停止)。这里我们使用 on
关键字进行迭代,这意味着依次访问每个子列表。由于我们使用 by #'cddr
,所有其他子列表都被跳过。解构语法 (a b)
绑定访问列表的第一个和第二个元素。
(defun double-every-other (xs)
(loop for x in xs
for doublep = nil then (not doublep)
collect (if doublep (* x 2) x)))
另一个版本,完全没有循环:
(defun make-cycled (&rest items)
(setf (cdr (last items)) items))
(mapcar #'funcall
(make-cycled #'identity (lambda (x) (* 2 x)))
'(10 9 8 7 6 5 4 3))
;;=> (10 18 8 14 6 10 4 6)
您可以使用 loop
"on" 列表迭代原语。这需要一个循环变量列表,这些变量将 "smeared" 遍历整个列表,最后一个是整个剩余列表的尾部。如果我们有奇数个参数,则有条件的 loop
是避免乘法 nil
所必需的。
(defun double-every-other (list)
(loop for (single double tail) on list by #'cddr
if (null double)
collect single
else
append (list single (* 2 double))))
如果我们尝试 运行 它:
* (double-every-other '(1 2 3 4 5))
(1 4 3 8 5)