我需要一个递归函数,它使用自定义过滤器函数来返回列表的模式。如果有多个模式,则应返回两者。
例如: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)?
答案 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))
可能有一种更简单的方法,但这确实有效。