最もよく現れるデータを見つけたい - lisp-cookbook-ja/common-lisp GitHub Wiki

ハッシュ

最もよく現れるデータを見つけたい

アイテムの出現数を記録し、最大のものを見付けるにはハッシュテーブルを利用する方法等が考えられるでしょう。FIXME

(defgeneric most-common (container &key test)
  (:method (container &key (test #'equal))
    (let ((count (count-item (make-hash-table :test test) 
                             container))
          (max 0) 
          max-var)
      (loop :for val :being :each :hash-values :of count 
                                  :using (:hash-key key)
            :do (when (< max val) 
                  (setq max val
                        max-var key)))
      (values max-var max)))))
(defmethod most-common ((table null) &key test) 
  (values nil nil))

(defgeneric count-item (table container))
(defmethod count-item (table (list list))
  (symbol-macrolet ((hv (gethash elt table)))
    (loop :for elt :in list
          :do (multiple-value-bind (val win) hv
                (if win (incf hv) (setf hv 1)))))
  table)

;; 実行例
(let ((list '(1 2 3 1 2 3 1 2 3 4 5 4 2 1 2 3 3 2 5 8)))
  (most-common list :test #'eql))
;=> 2 ;値
;   6 ;回数

議論