前回、前々回とリストに対する関数、集合として扱う際の関数を学んできた。今回はリストをテーブルとして扱っていく。
前回の記事はこちら。
Contents
この記事に出てくる関数一覧
function | description |
---|---|
assoc | key入力に対して該当するvalueを返す |
rassoc |
リストをテーブルとして扱う
例として以下のテーブルを考えてみる。
key | a | b | c | d |
---|---|---|---|---|
value | Hokkaido | Honshu | Shikoku | Kyushu |
これをリストで以下のように表す。
(setf sample-table (list '(a "Hokkaido") '(b "Honshu") '(c "Shikoku") '(d "Kyushu")))
これに対してaに対応するHokkaidoを探し出すことが最もシンプルな形だろう。
assoc: keyから要素を返す
assocを使うことでkeyに該当する要素を得ることができる。
基本の形
(assoc key alist)
実際に上のテーブルに試してみよう。
(assoc 'a sample-table) ; => (A "Hokkaido") (assoc 'b sample-table) ; => (B "Honshu") (assoc 'c sample-table) ; => (C "Shikoku") (assoc 'd sample-table) ; => (D "Kyushu") (assoc 'e sample-table) ; => NIL (assoc "Hokkaido" sample-table) ; => NIL
このように対応する対が返されるのでkeyに対応するvalueそのもの(例の場合aに対する"Hokkaido")が欲しい場合はさらにsecond
を適用する必要がある。
また基本の形のなかでalistと書いているがこれはassociation listのことである。またplist(parameter list)というものもある。
rassoc: valueから要素を返す
rassocを使うことでassocとは逆にvalueから該当する要素を得ることができる。
基本の形
(rassoc key alist)
ただしrassocの場合は要素がリストではなくドット対でなければならない。つまり上記で使ったテーブルに代わり以下のものを用意する。
(setf sample-table-dot (list '(a . hokkaido) '(b . honshu) '(c . shikoku) '(d . kyushu))) ; => ((A . HOKKAIDO) (B . HONSHU) (C . SHIKOKU) (D . KYUSHU))
このリストにrassocを使ってみよう。
(rassoc 'hokkaido sample-table-dot) ; => (A . HOKKAIDO) (rassoc 'honshu sample-table-dot) ; => (B . HONSHU) (rassoc 'shikoku sample-table-dot) ; => (C . SHIKOKU) (rassoc 'kyushu sample-table-dot) ; => (D . KYUSHU) (rassoc 'okinawa sample-table-dot) ; => NIL (rassoc 'a sample-table-dot) ; => NIL
assocと逆の検索ができていることがわかるだろう。
ちなみにドット対にassocを使用することはできる。
(assoc 'a sample-table-dot) ; => (A . HOKKAIDO)
比較に使われるオペレータ
上記の例でrassoc用に用意したドット対では文字列ではなくシンボルを使用している。なぜかというと文字列だとrassocそのまま使用した場合にうまく値が返ってこない。
以下に実例を示す。
(setf sample-table-dot-2 (list '(a . "Hokkaido") '(b . "Honshu") '(c . "Shikoku") '(d . "Kyushu"))) ; => ((A . "Hokkaido") (B . "Honshu") (C . "Shikoku") (D . "Kyushu")) (rassoc "Hokkaido" sample-table-dot-2) ; => NIL
これは比較のために使われるデフォルトのオペレータによって引き起こされている。assoc, rassocともに比較に使うオペレータを指定することができ、それをequal
にすると期待した動きにはなる。
(rassoc "Hokkaido" sample-table-dot-2 :test #'equal) ; => (A . "Hokkaido")
コロンで始まるキーワードについてはまた別の機会に記事にしたいと思うがそれを用いて比較用のオペレータをequalに指定すると対応する要素を取り出せていることがわかるだろう。
これは集合ででてきたmember
等でも同じことがいえる。等価であることを調べるオペレータはたくさんあるのでその違いもいずれ別の記事にしたい。
まとめ
3回続けてリストをいじる記事を書いてきた。まだまだ完全に自分のもににはできていないが引き続き慣れていきたい。
append
でリスト同士を連結できるreverse
でリストを逆順にできるnth
,nthcdr
でcar
,cdr
,cadr
,cddr
...を一般化できるlast
でリストの最後の要素を得るremove
でリストの要素を削除する- リストを集合として扱うこともできる
- memberで要素を調べる
- intersectionで積集合
- unionで和集合
- sub-differenceで差集合
- subsetpで部分集合かどうかを調べる
- adjoinで要素追加
- リストをテーブルとして扱うこともできる
- assoc、rassocでテーブル検索できる
ここまでで扱いきれなかった内容として以下がある。これらもいずれ記事としたい。
- リスト演算の効率
- 等価を評価する種々のオペレータ
- plist
- ハッシュテーブル
- リストを用いたtree構造
- キーワード
コメント