:keyの活用 - lisp-cookbook-ja/common-lisp GitHub Wiki
Common Lispのシークエンスを扱う関数には:keyに関数を指定することで、読み出し方法を指定することが可能なことがあります。
:keyを活用すれば、オブジェクトのスロットの値によってソートする等のことが可能です。
また、標準以外のライブラリなどでも、この規約に沿ったものが多くあります。
:key が利用できるCL標準の関数は下記の通りです
adjoin, assoc, assoc-if, assoc-if-not, find, find-if, find-if-not, intersection, member, member-if, member-if-not, merge, nintersection, nset-difference, nset-exclusive-or, nsublis, nsubst, nsubst-if, nsubst-if-not, nunion, position, position-if, position-if-not, pushnew, rassoc, rassoc-if, rassoc-if-not, set-difference, set-exclusive-or, sort, stable-sort, sublis, subsetp, subst, subst-if, subst-if-not, union
コード例
下記の例では、オブジェクトのプロパティを:keyで拾うことにより、抽出、ソート、グループ化をしています。
(ユーザー定義の関数の例として、com.informatimago.common-lisp.list:equivalence-classesを利用しています。)
(import 'com.informatimago.common-lisp.list:equivalence-classes)
;;; データ(購入者名 商品名 購入日時(universal time))
(defclass item ()
((purchase-date :accessor purchase-date :initarg :purchase-date)
(purchaser :accessor purchaser :initarg :purchaser)
(product-name :accessor product-name :initarg :product-name)))
(defvar *items*
(mapcar (lambda (p n d)
(make-instance 'item
:purchaser p
:product-name n
:purchase-date d))
'("おそ松" "カラ松" "チョロ松" "一松" "十四松" "トド松")
'("テレビ" "テレビ" "エアコン" "ノートPC" "扇風機" "掃除機")
'(3512674686 3556829851 3543518696 3526561150 3514854835 3529844173)))
;;; 期間でしぼりこみ
(defun between (fn start-ut end-ut items)
(remove-if-not (lambda (i)
(<= start-ut i end-ut ))
items
:key fn))
;;; オブジェクトのスロットでソート
(defun order-by (fn items)
(sort items #'< :key fn))
;;; オブジェクトのスロットでグループ化
(defun group-by (fn items)
(equivalence-classes items :test #'string= :key fn))
;;; アイテムをプリント
(defun print-item (item)
(let ((item (if (consp item) item (list item))))
(format t "商品 = ~A~%" (product-name (car item)))
(dolist (e item)
(format t "~4T購入者は、~Aさん~%" (purchaser e)) )))
;;; 実行
(dolist (item (group-by #'product-name
(order-by #'purchase-date
(between #'purchase-date
(encode-universal-time 0 0 0 1 1 2011)
(encode-universal-time 0 0 0 31 12 2013)
*items*))))
(print-item item))
;-> 商品 = エアコン
; 購入者は、チョロ松さん
; 商品 = 掃除機
; 購入者は、トド松さん
; 商品 = ノートPC
; 購入者は、一松さん
; 商品 = 扇風機
; 購入者は、十四松さん
; 商品 = テレビ
; 購入者は、カラ松さん
; 購入者は、おそ松さん
;
;=> NIL