Filter 查找列表的模式(在common LISP中)

Filter 查找列表的模式(在common LISP中),filter,lisp,common-lisp,Filter,Lisp,Common Lisp,我需要一个递归函数,它使用一个自定义过滤器函数来返回列表的模式。如果存在多个模式,则应同时返回两个模式 例如:L=(1 3 5 2 3 5)-->((3 2)(5 2)) 其中,第一个数字是列表中的元素,第二个数字是列表中出现的次数 我有计算事件的函数: ;;;功能名称:occr2 ;;; 描述:函数统计列表中元素的所有出现次数 ;;; 注:模型的辅助函数 (除occr2(KL) (条件((空L)0) ((eql k(第一个L))(+1(occr2 k(其余L))) (t(occr2k)(其余L

我需要一个递归函数,它使用一个自定义过滤器函数来返回列表的模式。如果存在多个模式,则应同时返回两个模式

例如:L=(1 3 5 2 3 5)-->((3 2)(5 2)) 其中,第一个数字是列表中的元素,第二个数字是列表中出现的次数

我有计算事件的函数:

;;;功能名称:occr2
;;; 描述:函数统计列表中元素的所有出现次数
;;; 注:模型的辅助函数
(除occr2(KL)
(条件((空L)0)
((eql k(第一个L))(+1(occr2 k(其余L)))
(t(occr2k)(其余L()))
;;; 功能名称:occr
;;; 描述:函数返回列表中每个元素的出现列表
;;; 注:模型的辅助函数
(除occr(L)
(条件((空L)无)
(t)(cons(cons(first L)(cons(occr2(first L)L)(occr(remv(first L)
当我在列表上运行此命令时(1 3 5 2 3 5)-->((1 1)(3 2)(5 2)(2 1))
现在,如何使用递归过滤函数仅返回(3 2)和(5 2)?

可能有一种更直接的方法来计算列表的模式,但由于已经有一个“直方图”函数返回每个元素及其频率的列表,您可以使用argmax函数来查找频率最大化的元素:

(defun argmax (function list)
  "ARGMAX returns a list of the elements of LIST that maximize
FUNCTION."
  (if (endp list)
      (error "Cannot maximize over an empty list.")
      (destructuring-bind (best &rest list) list
        (do* ((bests (list best))
              (max (funcall function best)))
             ((endp list) bests)
          (let* ((x (pop list))
                 (val (funcall function x)))
            (cond
              ((> val max)
               (setf bests (list x)
                     max val))
              ((= val max)
               (push x bests))))))))


以下是我最终能想到的。对于我的类,我们不允许使用内置函数。我基本上找到任何值的最高出现次数,并将每个元素出现次数与该值进行比较,过滤掉任何小于模式值的元素。这样,如果2+个元素具有相同的引用,过滤器仍会保留它们

;;;功能名称:occr2
;;; 描述:函数统计列表中元素的所有出现次数
;;; 注:模型的辅助函数
(除occr2(KL)
(条件((空L)0)
((eql k(第一个L))(+1(occr2 k(其余L)))
(t(occr2k)(其余L()))
;;; 功能名称:occr
;;; 描述:函数返回列表中每个元素的出现列表
;;; 注:模型的辅助函数
(除occr(L)
(条件((空L)无)
(t)(cons(cons(first L)(cons(occr2(first L)L)(occr(remv(first L)
;;; 函数名称:过滤器
;;; 描述:函数根据布尔函数参数从列表中筛选元素
;;; 注:模型的辅助函数
(除油过滤器(左)
(条件((空L)无)
((funcall F(first L))(cons(first L)(filter F(rest L)))
(t(过滤器F(其余的L‘‘)’))
;;; 函数名称:findmax
;;; 描述:函数查找列表中元素的最大出现次数
;;; 注:模型的辅助函数
(defun findmax(L)
(第二个((空(剩余L))(第二个(第一个L)))
((>(第二(第一个L))(第二(第二个L)))
(findmax(cons(first L)(rest(rest L()()))))
(t(findmax(cons(second L)(rest(rest L)(()()))))
;;; 功能名称:模型
;;; 描述:函数使用过滤器返回元素列表的模式
;;; 注意:使用occr、occr2、filter和findmax辅助函数
(除油模式(L)
(滤波器(λ(x)
(>=(第二个x)(findmax(occr L)))
(occr(L)))
(型号"1 3 5 2 3 5)-->(3 2)(5 2)

(型号"1 3 5 2 4 5)-->(5 2)


也许有一种更简单的方法可以做到这一点,但这确实有效。

除了家庭作业之外,它可能看起来像这样:

(defun mode (l &aux (table (make-hash-table)))
  (loop for e in l do (incf (gethash e table 0)))
  (let ((max (loop for v being the hash-value of table maximize v)))
    (loop for key being the hash-keys of table using (hash-value value)
          when (eql value max)
          collect (list key value))))

“如果有多个模式,则应同时返回两个模式。”如果有多个模式,则也可能有多个模式。由于您已经能够执行
(1 3 5 2 3 5)-->((1 1)(3 2)(5 2)(2 1))
,因此您需要的是一个argmax函数,它可以最大化子列表的第二个元素。(术语可能有助于研究。)中的一些技术可能会有所帮助。在
模型中
:不止一次计算
findmax
不是一个好主意。“我们不允许使用内置函数”你应该在问题中提到这一点。您仍然在使用许多内置函数:null、rest、second、first、>、cons和eql等等。如果你有一个关于你能用什么不能用的具体要求,你需要在问题中提到它。无论如何,如果这是对您有效的解决方案,请确保在任何时间限制结束后完成。
(defun mode (l &aux (table (make-hash-table)))
  (loop for e in l do (incf (gethash e table 0)))
  (let ((max (loop for v being the hash-value of table maximize v)))
    (loop for key being the hash-keys of table using (hash-value value)
          when (eql value max)
          collect (list key value))))