同じ年月は同じグループとしてカウントして数を求める例でのコード比較を Common Lisp でも — #:g1

Posted 2010-11-13 13:05:00 GMT

-(http://blog.fukaoi.org/2010/10/12/Scala%E3%80%81Java%E3%80%81PHP%E3%81%A7%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E9%87%8F%E3%82%92%E6%AF%94%E8%BC%83%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)
sumimさんの(http://d.hatena.ne.jp/sumim/20101112/p1)経由

まけるなCommon Lisp。しかし、ライブラリを使ってる時点で反則かもしれず。
最近、comp.lang.schemeで似たような質問があったんですが、そのスレッドの回答で見かけたequivalence-classesというのを使ってみました。

;;---(logic)----で囲んだ箇所を比較対象箇所とする
(import 'com.informatimago.common-lisp.list:equivalence-classes)

(defvar *year-months* '("2009-11" "2009-01" "2010-01" "2010-12" "2010-01" "2010-04" "2010-01" "2010-12" "2010-12" "2010-04"))

;;---(logic)---- (mapcar (lambda (x) (cons (car x) (length x))) (sort (equivalence-classes *year-months* :test #'string=) #'string< :key #'car)) ;;---(logic)---- ;=> (("2009-01" . 1) ("2009-11" . 1) ("2010-01" . 3) ("2010-04" . 2) ; ("2010-12" . 3))


無駄にSeriesで頑張ってみる

;; series::*series-implicit-map* ;=> T
(let ((ans () ))
  (iterate ((item (scan *year-months*)))
    (let ((place (member item ans :key #'car :test #'string=)))
      (if place
          (push item (car place))
          (push (list item) ans))))
  (series::let* ((ym (scan ans))
                 (ym.sum (cons (car ym) (length ym))))
    (alter ym ym.sum)
    (sort ans #'string< :key #'car)))
;=> (("2009-01" . 1) ("2009-11" . 1) ("2010-01" . 3) ("2010-04" . 2)
;    ("2010-12" . 3))
長い…まあ、equivalence-classesを使えば…
(series::let* ((ym (scan (equivalence-classes *year-months* :test #'string=)))
               (ym.sum (cons (car ym) (length ym))))
  (sort (collect ym.sum) #'string< :key #'car))
;=> (("2010-04" . 2) ("2010-12" . 3) ("2010-01" . 3) ("2009-01" . 1)
;    ("2009-11" . 1))

;; LetS風 (letS* ((ym (Elist (equivalence-classes *year-months* :test #'string=))) (ym.sum (cons (car ym) (length ym)))) (sort (Rlist ym.sum) #'string< :key #'car)) ;=> (("2010-04" . 2) ("2010-12" . 3) ("2010-01" . 3) ("2009-01" . 1) ; ("2009-11" . 1))


comments powered by Disqus