将列表简化成其元素差异的总和

时间:2018-12-14 10:55:04

标签: list common-lisp reduce

我有一个简单的列表,整数总是像偶数一样

(42 38 15 5)

我想计算其对之差的总和,即

(+ (- 42 38) (+ 15 5)) --> 14

可以是2个,4个或更多元素,但始终为偶数。我以为会有一种使用reduce的方法,但是我看不到正确的配对方法。

是否有一种简单的方法来执行此操作,或者更容易更改列表结构?例如类似

((42 38) (15 5))

2 个答案:

答案 0 :(得分:4)

您可以使用loop

(loop :for (a b) :on list :by #'cddr
      :sum (- a b))

for-on的结构超出列表的尾部,for可以解构,by提供步进功能(默认为#'cdr

如果您绝对想使用高阶函数,则需要先进行分区(如您所推测的那样),或者找到一种步进机制。

可以再次通过loop或通过伪造来进行分区。之后,您可以减少:

(reduce (lambda (sum pair)
          (+ sum (apply #'- pair)))
        (partition 2 list)
        :initial-value 0)

或者,您可以将其视为交替地加减数字:

(reduce #'+
        (mapcar #'funcall
                (circular-list #'+ #'-)
                list))

({Circular-list来自alexandria。)

答案 1 :(得分:2)

您还可以使用较短的循环:

(loop 
   while list 
   sum (- (pop list)
          (pop list)))