查找列表的最多出现次数并返回以最有效的ele开头的列表

时间:2016-02-14 04:22:49

标签: lisp common-lisp

(defun occurrences (l)
(let (
        (result (mapcar #'(lambda (elt) (cons elt (count elt l)) ) 
            (remove-duplicates l)   )   )
        (result2 nil)  
        (result3 nil)
        (result4 nil)
    )
(progn
    (sort result #'> :key #'cdr)
    (loop for x in result
        do (and(push (car x) result2)(push (cdr x) result3))
    )
)))

这应该按升序返回排序列表。除了不应返回重复次数最少的元素(与列表的其余部分合同)。除非所有元素重复相同的次数,否则只有在这种情况下才会返回所有元素。

例如,

  1. (出现'(1 2 3))=> (1 2 3),#notice每个元素重复相同的次数。

  2. (出现'(1 1 3))=> (1)#since,其中1比列表中的任何其他元素更频繁发生。

  3. 3(发生'(1 2 3 4 6 6 6 6))=> (6)

    1. (出现'(1 1 3 3 0))=> (1,3)。 #since(1 2),(3 2)和(0 1) 因为元素1和3的出现仍然高于此列表中至少一个元素的出现。
    2. 注意:此时此函数返回一个已排序的列表,但错误地返回最大值(occ的数量)加上元素,这些元素的出现次数至少不大于列表中的另一个元素。 防爆。 (发生'(7 7 7 1 2 3))返回(7 1 2 3),但应该只返回7.我真的很感谢帮助修复此函数以返回预期的内容。

1 个答案:

答案 0 :(得分:2)

使用您的初始方法的解决方案如下:

(defun max-occurrences(l)
  (let* ((occurrences (remove-duplicates 
                        (mapcar #'(lambda (elt) (cons elt (count elt l))) l) 
                        :test 'equal))
         (max-occurrence (reduce #'max occurrences :initial-value 0 :key #'cdr)))
    (mapcar #'car (remove-if-not (lambda(x) (= x max-occurrence)) occurrences :key #'cdr))))

然而,这种解决方案效率不高,因为它的成本为O(n 2 )(在初始阶段,列表的每个元素与所有其他元素进行比较以计算其频率)。

被修改

例如,通过使用哈希表(在@uselpa的评论中建议改进),可以获得更有效的解决方案:

(defun max-occurrences(l)
   (let* ((table (make-hash-table))
          (max-count (loop for elt in l maximize (incf (gethash elt table 0)))))
     (loop for elt being the hash-key of table using (hash-value count)
        when (= count max-count) collect elt)))