LISP函数-返回列表中大于第一个元素的数字的计数

LISP函数-返回列表中大于第一个元素的数字的计数,lisp,common-lisp,Lisp,Common Lisp,我想解一个lisp函数,它返回一个大于列表中第一个数字的数字计数。列表是一个线性数字列表 (defun foo (lst) (cond ((null lst) 0) (car = k) ((> (car lst) k) (1+ (foo (cdr lst)))) (T (foo (cdr lst))))) 我的问题是,我无法保留第一个元素并将其与其他元素进行比较。您的函数正确缩进如下所示: (defun greater-than

我想解一个lisp函数,它返回一个大于列表中第一个数字的数字计数。列表是一个线性数字列表

(defun foo (lst) 
  (cond ((null lst) 0)
        (car = k)
        ((> (car lst) k) 
        (1+ (foo (cdr lst))))
  (T (foo (cdr lst)))))

我的问题是,我无法保留第一个元素并将其与其他元素进行比较。

您的函数正确缩进如下所示:

(defun greater-than-100 (number)
    (> number 100))
 (lambda (x) (foo known x))
德芬福斯特酒店 cond null lst 0 car=k;奇异第二项 >汽车lst k 1+foo cdr lst T foo cdr lst 我已经评论了你的第二个任期。这很奇怪。它首先评估变量car,而不是函数car。如果car不是nil,它首先计算变量=而不是函数'=并且因为它不是第二项中的最后一个后续表达式,所以它会丢弃它并返回最后一个,即k

第二,你写你说你使用第一个元素作为比较,但是你在你的函数中称它为k,但是它没有在任何地方定义。在执行递归之前需要做一些事情,因此不能让实际函数执行递归,因为它每次都会使用第一个元素。以下是可以使用标签的位置:

;; 没有叫它foo,因为它不是很有描述性 defun计数大于第一个列表 让我们把第一辆车列出来 标签帮助器列表 cond null列表0 >汽车清单第一 1+助手cdr列表 t助手cdr列表 助手cdr列表 当然。既然您现在可以添加更多参数,我会添加一个累加器:

defun计数大于第一个列表 让我们把第一辆车列出来 标签帮助器列表acc 条件空列表acc >汽车清单第一 助手cdr列表1+acc t助手cdr列表acc 帮助程序cdr列表0 当然,递归可能会破坏堆栈,因此您应该在不使用Common Lisp的情况下编写它:

defun计数大于第一个列表 让我们把第一辆车列出来 循环:对于cdr列表中的元素 :计数>元素优先 还有更适合计算的高阶函数:

defun计数大于第一个列表 让我们把第一辆车列出来 如果lambda元素>元素优先,则计数 cdr列表
让我们来分析一下你的问题:

你有一组数字。真的,你有一个“特殊”的第一个号码,然后是其他号码。具体来说,您可能只需要实数,因为“小于”对于复数来说没有意义

您可以使用first从列表中获取第一个数字,其余的用于其他数字

其中,您要计算不大于第一个值的任何值

让我们从伪代码开始

(defun count-numbers-greater-than-first (list)
  ;; split out first and rest
  ;; call the real count function
  )
好的,我们现在知道我们可以使用first和rest,正如您使用的,历史上的car和cdr,所以:

您可能已经知道>用于测试实数是否大于其他实数

快速查看CLHS可以发现一个很好的函数,名为count if

那个???必须是函数类型的对象,或函数的名称。我们需要将引用的第一个数字“curry”到该函数中。这意味着我们要创建一个新函数,该函数仅用于一次运行计数if,它已经“关闭”了引用值

如果我们知道这个数字总是,比如说,100,那么这个函数会是这样的:

(defun greater-than-100 (number)
    (> number 100))
 (lambda (x) (foo known x))
如果出现以下情况,则可在计数中使用该函数:

但这并不能解决将参考号“curried”放入函数中的问题

在不涉及Alexandria的情况下,我马上解释一下,您可以使用lambda表单在这里创建一个新的匿名函数。由于引用在不大于的计数中可用,因此可以在该lambda中使用其值。让我们先换算为100:

(defun count-numbers-greater-than (reference other-numbers)
    (count-if (lambda (number) (> number 100))
              other-numbers))
现在我们可以参考:

事实上,如果您愿意,您甚至可以将此函数合并回另一个函数:

(defun count-numbers-greater-than-first (list)
    (count-if (lambda (number) (> number (first list)))
              (rest list)))
亚历山大的那件事 但是,亚历山大怎么样?Alexandria是Quicklisp或其他地方提供的超级有用的实用程序函数的集合

 (ql:quickload "alexandria")

 (use-package #:alexandria)
当然,您通常会在自己的软件包中使用它

它提供的两个功能是curry和rcurry函数。事实证明,这里的lambda函数是一种非常常见的情况。您有一个现有的函数-这里是>-您想用相同的值反复调用,还有一些未知的值,您想每次传入

这些最终看起来非常像这样:

(defun greater-than-100 (number)
    (> number 100))
 (lambda (x) (foo known x))
你可以用咖喱更简洁地写同样的东西:

 (curry #'foo known)
它还可以处理任意数量的参数。RCurry也这样做,但它将未知值“x”放在左侧,将已知值放在右侧

 (lambda (x) (foo x known)) = (rcurry #'foo known)
因此,另一种写入计数的方法是:


到目前为止你尝试了什么?德芬
foo lst cond null lst 0 car=k>car lst k 1+foo cdr lst foo cdr lstim不太熟悉lisp,因为我是新手..我认为我很接近,但我的问题是我无法保留第一个元素并将其与others@TasosCe:您不能“保留第一个元素”是什么意思?你知道什么是变量吗?非常感谢你的帮助。我测试了它,它工作得很好!另外,感谢您在开始时提供的有用建议,我理解关于我在k和标签使用上的错误的一切:!!哇,非常感谢您的解释,每个解决方案都非常完美,完全可以理解!
 (lambda (x) (foo x known)) = (rcurry #'foo known)
(defun count-numbers-greater-than-first (list)
    (count-if (rcurry #'> (first list))
              (rest list)))

 * (count-numbers-greater-than-first '(10 9 8 7 11 12))

 2