在Common Lisp中查找嵌套列表的平均值

在Common Lisp中查找嵌套列表的平均值,lisp,common-lisp,average,nested-lists,Lisp,Common Lisp,Average,Nested Lists,我一直在努力寻找嵌套列表的平均值,这就是我目前所拥有的: (defun nested-average2 (tree &optional (sum 0) (count 0)) (cond ((null tree) (/ sum count)) ((listp (first tree)) (nested-average2 (rest tree) (nested-average2 (fi

我一直在努力寻找嵌套列表的平均值,这就是我目前所拥有的:

(defun nested-average2 (tree &optional (sum 0) (count 0))
  (cond ((null tree)
         (/ sum count))
        ((listp (first tree))
         (nested-average2 (rest tree)
                          (nested-average2 (first tree) sum)
                          (incf count)))
        (t
         (nested-average2 (rest tree)
                          (+ sum (first tree))
                          (incf count)))))    
但是,它返回非整数


例如,使用这个
(nested-average2'(10((30 1)20)(8(5(50 7))9)40))
,当它应该返回18时,它返回2425/192。您的代码适用于普通列表,但不适用于子列表

  • 其中一个问题是,当您在子列表上递归时,count只增加1,而不是增加已处理的元素数
  • 另一种情况是,在这种情况下,你已经计算出一个“次平均值”,你把它加到总和上
最简单的方法是计算总和和计数,直到完成整棵树;只有这样,您才应该进行最后的除法来计算平均值,例如:

(defun nested-average (sxp)
  (labels
      ((sub (sxp tot cnt)
         (cond
          ((null sxp)  (values tot cnt))
          ((consp sxp) (multiple-value-bind (tot1 cnt1) (sub (car sxp) tot cnt)
                         (sub (cdr sxp) tot1 cnt1)))
          (t           (values (+ tot sxp) (1+ cnt))))))
    (multiple-value-bind (tot cnt) (sub sxp 0 0)
      (/ tot cnt))))

您的代码适用于普通列表,但不适用于子列表

  • 其中一个问题是,当您在子列表上递归时,count只增加1,而不是增加已处理的元素数
  • 另一种情况是,在这种情况下,你已经计算出一个“次平均值”,你把它加到总和上
最简单的方法是计算总和和计数,直到完成整棵树;只有这样,您才应该进行最后的除法来计算平均值,例如:

(defun nested-average (sxp)
  (labels
      ((sub (sxp tot cnt)
         (cond
          ((null sxp)  (values tot cnt))
          ((consp sxp) (multiple-value-bind (tot1 cnt1) (sub (car sxp) tot cnt)
                         (sub (cdr sxp) tot1 cnt1)))
          (t           (values (+ tot sxp) (1+ cnt))))))
    (multiple-value-bind (tot cnt) (sub sxp 0 0)
      (/ tot cnt))))

以下内容与Le Petit Prince类似,但没有本地函数返回多个值。基本上,这是深度优先行走,在树叶上求和计数

(defun nested-average2 (tree)
  (let ((sum 0)
        (cnt 0))
    (labels ((leaf-sum-cnt (branch)
               (cond ((null branch))          ; nothing
                     ((listp branch)          ; follow the branches
                      (leaf-sum-cnt (car branch))
                      (leaf-sum-cnt (cdr branch)))
                     (t (incf sum branch)     ; at a leaf
                        (incf cnt)))))
      (leaf-sum-cnt tree)
      (/ sum cnt))))

当然,这个例子不是很实用。因此,如果这是家庭作业,您的教授可能不喜欢。

以下内容类似于Le Petit Prince,但没有返回多个值的局部函数。基本上,这是深度优先行走,在树叶上求和计数

(defun nested-average2 (tree)
  (let ((sum 0)
        (cnt 0))
    (labels ((leaf-sum-cnt (branch)
               (cond ((null branch))          ; nothing
                     ((listp branch)          ; follow the branches
                      (leaf-sum-cnt (car branch))
                      (leaf-sum-cnt (cdr branch)))
                     (t (incf sum branch)     ; at a leaf
                        (incf cnt)))))
      (leaf-sum-cnt tree)
      (/ sum cnt))))

当然,这个例子不是很实用。因此,如果这是作业,您的教授可能不喜欢。

您好,谢谢您回复我,不幸的是,尽管我无法真正理解代码在做什么?如果您使用的是局部函数,没有意义传递并返回tot和cntHi感谢您回复我,不幸的是,虽然我不能真正理解代码在做什么?如果您使用的是本地函数,那么传递和返回tot和cnt就没有意义了