リストをフィルターする関数

May 15, 2010   #gauche  #Lisp  :

2010-05-11 – 武蔵の日記で予告していたリストをフィルタリングする関数を作成してみました:

作成してみた関数

(define (filter-list-by key-fn value cmp xs)
(map cdr
(filter (lambda (x)
(if (cmp (car x) value)
#t
#f))
(map
(lambda (x)
(cons (key-fn x) x))
xs))))

実行例

;; 前提になるライブラリを読み込む
gosh> (use srfi-1)
#<undef>
gosh> (use sxml.ssax)
#<undef>
gosh> (use sxml.sxpath)
#<undef>
;; 前提になる get-value-from-sxml を定義
gosh> (define (get-value-from-sxml sxpath sxml)
((if-car-sxpath `(// ,sxpath *text*)) sxml))
get-value-from-sxml
;; type が photo のものを抽出する
gosh> (let ((sxml
'((post (|@|
(type "quote")
(id "547214365")))
(post (|@|
(type "quote")
(id "1234567890")))
(post (|@|
(type "photo")
(id "foo"))))))
(filter-list-by (lambda (x)
(get-value-from-sxml 'type x))
"photo"
equal?
sxml))
((post (|@| (type "photo") (id "foo"))))
;; type が quote のものを抽出する
gosh> (let ((sxml
'((post (|@|
(type "quote")
(id "547214365")))
(post (|@|
(type "quote")
(id "1234567890")))
(post (|@|
(type "photo")
(id "foo"))))))
(filter-list-by (lambda (x)
(get-value-from-sxml 'type x))
"quote"
equal?
sxml))
((post (|@| (type "quote") (id "547214365"))) (post (|@| (type "quote") (id "1234567890"))))
;; 当然だけど、 quot (存在しないもの)を指定したら空リストが戻る
gosh> (let ((sxml
'((post (|@|
(type "quote")
(id "547214365")))
(post (|@|
(type "quote")
(id "1234567890")))
(post (|@|
(type "photo")
(id "foo"))))))
(filter-list-by (lambda (x)
(get-value-from-sxml 'type x))
"quot"
equal?
sxml))
()

こういうフィルタリングする関数は定石としてどのように処理するんだろう? Lisp の定石集みたいなのがあるといいなと、ふと思いました。