找到列表的模式(在共同的LISP中)

时间:2014-11-29 22:05:02

标签: filter lisp common-lisp

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

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

我有计算事件的函数:

;;; FUNCTION NAME: occr2
;;; DESCRIPTION: function counts all occurrences of an element in a list
;;; NOTES: helper function for model

(defun occr2 (k L)
    (cond ((null L) 0)
          ((eql k (first L)) (+ 1 (occr2 k (rest L))))
          (t (occr2 k (rest L)))))

;;; FUNCTION NAME: occr
;;; DESCRIPTION: function returns list of occurrence of each element in a list
;;; NOTES: helper function for model

(defun occr (L)
    (cond ((null L) NIL)
          (t (cons (cons (first L) (cons (occr2 (first L) L) NIL)) (occr (remv (first L) L))))))

当我在列表上运行时('1 3 5 2 3 5) - > ((1 1)(3 2)(5 2)(2 1)) 现在,我如何使用递归过滤函数只返回(3 2)和(5 2)?

3 个答案:

答案 0 :(得分:1)

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

(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 :(得分:0)

可能有一种更直接的方式来计算列表的模式,但是因为你已经有一个"直方图"函数返回每个元素及其频率的列表,你可以使用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))))))))

CL-USER> (argmax 'second '((1 1) (3 2) (5 2) (2 1)))
((5 2) (3 2))

答案 2 :(得分:0)

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

;;; FUNCTION NAME: occr2
;;; DESCRIPTION: function counts all occurrences of an element in a list
;;; NOTES: helper function for model

(defun occr2 (k L)
    (cond ((null L) 0)
          ((eql k (first L)) (+ 1 (occr2 k (rest L))))
          (t (occr2 k (rest L)))))

;;; FUNCTION NAME: occr
;;; DESCRIPTION: function returns list of occurrence of each element in a list
;;; NOTES: helper function for model

(defun occr (L)
    (cond ((null L) NIL)
          (t (cons (cons (first L) (cons (occr2 (first L) L) NIL)) (occr (remv (first L) L))))))

;;; FUNCTION NAME: filter
;;; DESCRIPTION: function filters elements out of a list based on a boolean function parameter
;;; NOTES: helper function for model

(defun filter (F L)
    (cond ((null L) NIL)
          ((funcall F (first L)) (cons (first L) (filter F (rest L))))
          (t (filter F (rest L)))))

;;; FUNCTION NAME: findmax
;;; DESCRIPTION: function finds the max occurrence of elements in a list
;;; NOTES: helper function for model

(defun findmax (L)
    (cond ((null (rest L)) (second (first L)))
          ((> (second (first L)) (second (second L)))
           (findmax (cons (first L) (rest (rest L)))))
          (t (findmax (cons (second L) (rest (rest L)))))))

;;; FUNCTION NAME: model
;;; DESCRIPTION: function uses filter to return the mode(s) of a list of elements
;;; NOTES: uses occr, occr2, filter, and findmax helper functions

(defun model (L)
  (filter (lambda (x)
            (>= (second x) (findmax (occr L))))
          (occr L)))

(model'(1 3 5 2 3 5)) - > ((3 2)(5 2))

(model'(1 3 5 2 4 5)) - > ((5 2))

可能有一种更简单的方法,但这确实有效。