Next: , Previous: , Up: リスト   [Contents][Index]


5.7 集合としてのリストの使用

リストは順序なしの数学的集合 — リスト内に要素があれば集合の要素の値としてリスト内の順序は無視される — を表すことができます。2つの集合を結合(union)するには、(重複する要素を気にしなければ)appendを使用します。equalである重複を取り除くにはdelete-dupsseq-uniqを使用します。集合にたいする他の有用な関数にはmemqdelqや、それらのequalバージョンであるmemberdeleteが含まれます。

Common Lispに関する注意: 集合を処理するためにCommon Lispには関数union (要素の重複がない)とintersectionがある。Emacs Lispではcl-libがこれらの変種を提供する。Lists as Sets in Common Lisp Extensionsを参照のこと。

Function: memq object list

この関数はobjectlistのメンバーかどうかをテストする。メンバーならmemqは、objectで最初に見つかった要素から開始されるリストをリターンする。メンバーでなければnilをリターンする。memqの文字‘q’は、この関数がobjectとリスト内の要素の比較にeqを使用することを示す。たとえば:

(memq 'b '(a b c b a))
     ⇒ (b c b a)
(memq '(2) '((1) (2)))    ; 2つの(2)eqである必要はない未定義; nil((2))かも
Function: delq object list

この関数はlistからobjecteqであるような、すべての要素を破壊的に取り除いて結果のリストをリターンする。delqの文字‘q’は、この関数がobjectとリスト内の要素の比較にeqを使用することを示す(memqremqと同様)。

delqを呼び出すときは、通常は元のリストを保持していた変数にリターン値を割り当てて使用する必要がある(理由は以下参照)。

delq関数がリストの先頭にある要素を削除する場合は、単にリストを読み進めてこの要素の後から開始される部分リストをリターンします。つまり:

(delq 'a '(a b c)) ≡ (cdr '(a b c))

リストの途中にある要素を削除するときは、必要なCDR (リストのCDRの変更を参照)を変更することで削除を行います。

(setq sample-list (list 'a 'b 'c '(4)))
     ⇒ (a b c (4))
(delq 'a sample-list)
     ⇒ (b c (4))
sample-list
     ⇒ (a b c (4))
(delq 'c sample-list)
     ⇒ (a b (4))
sample-list
     ⇒ (a b (4))

(delq 'a sample-list)は何も取り除きませんが(単に短いリストをリターンする)、(delq 'c sample-list)は3番目の要素を取り除いてsample-listを変更することに注意してください。引数listを保持するように形成された変数が、実行後にもっと少ない要素になるとか、元のリストを保持すると仮定しないでください! かわりにdelqの結果を保存して、それを使用してください。元のリストを保持していた変数に結果を書き戻すことはよく行なわれます。

(setq flowers (delq 'rose flowers))

以下の例では、delqが比較しようとしている(list 4)sample-list内の(4)は、equalですがeqではありません:

(delq (list 4) sample-list)
     ⇒ (a c (4))

与えられた値とequalな要素を削除したい場合には、delete (以下参照)を使用してください。

Function: remq object list

この関数はobjecteqなすべての要素が除かれた、listのコピーをリターンする。remqの文字‘q’は、この関数がobjectとリスト内の要素の比較にeqを使用することを示す。

(setq sample-list (list 'a 'b 'c 'a 'b 'c))
     ⇒ (a b c a b c)
(remq 'a sample-list)
     ⇒ (b c b c)
sample-list
     ⇒ (a b c a b c)
Function: memql object list

関数memqleql(浮動小数点数の要素は値で比較される)を使用してメンバーとeqlを比較することにより、objectlistのメンバーかどうかをテストする。objectがメンバーなら、memqllist内で最初に見つかった要素から始まるリスト、それ以外ならnilをリターンする。

memqと比較してみよう:

(memql 1.2 '(1.1 1.2 1.3))  ; 1.21.2eql
     ⇒ (1.2 1.3)
(memq 1.2 '(1.1 1.2 1.3))  ; 2つの1.2eqである必要はない未定義; nil(1.2 1.3)かもしれない

以下の3つの関数はmemqdelqremqと似ていますが、要素の比較にeqではなくequalを使用します。同等性のための述語を参照してください。

Function: member object list

関数memberは、メンバーとobjectequalを使用して比較して、objectlistのメンバーかどうかをテストする。objectがメンバーなら、memberlistで最初に見つかったところから開始されるリスト、それ以外ならnilをリターンする。

memqと比較してみよう:

(member '(2) '((1) (2)))  ; (2) and (2) are equal.
     ⇒ ((2))
(memq '(2) '((1) (2)))    ; 2つの(2)eqである必要はない未定義; nil(2)かもしれない
;; 同じ内容の2つの文字列はequal
(member "foo" '("foo" "bar"))
     ⇒ ("foo" "bar")
Function: delete object sequence

この関数はsequenceからobjectequalな要素を取り除いて、結果のシーケンスをリターンする。

sequenceがリストなら、deletedelqに対応するように、membermemqに対応する。つまりこの関数はmemberと同様、要素とobjectの比較にequalを使用する。マッチする要素が見つかったら、delqが行なうようにその要素を取り除く。delqと同様、通常は元のリストを保持していた変数にリターン値を割り当てて使用する。

sequenceがベクターか文字列なら、deleteobjectequalなすべての要素を取り除いたsequenceのコピーをリターンする。

たとえば:

(setq l (list '(2) '(1) '(2)))
(delete '(2) l)
     ⇒ ((1))
l
     ⇒ ((2) (1))
;; lの変更に信頼性を要するときは
;; (setq l (delete '(2) l))と記述する。
(setq l (list '(2) '(1) '(2)))
(delete '(1) l)
     ⇒ ((2) (2))
l
     ⇒ ((2) (2))
;; このケースではlのセットの有無に違い
;; はないが他のケースに倣ってセットするべき
(delete '(2) [(2) (1) (2)])
     ⇒ [(1)]
Function: remove object sequence

この関数はdeleteに対応する非破壊的な関数である。この関数はobjectequalな要素を取り除いた、sequence(リスト、ベクター、文字列)のコピーをリターンする。たとえば:

(remove '(2) '((2) (1) (2)))
     ⇒ ((1))
(remove '(2) [(2) (1) (2)])
     ⇒ [(1)]

Common Lispに関する注意: GNU Emacs Lispの関数memberdeleteremoveはCommon Lispではなく、Maclispを継承する。Common Lispでは比較にequalを使用しない。

Function: member-ignore-case object list

この関数はmemberと同様だが、objectが文字列でcaseとテキスト表現の違いを無視する。文字の大文字と小文字は等しいものとして扱われ、比較に先立ちユニバイト文字列はマルチバイト文字列に変換される。

Function: delete-dups list

この関数はlistからすべてのequalな重複を破壊的に取り除いて、結果をlistに保管してそれをリターンする。list内の要素にequalな要素がいくつかあるなら、delete-dupsは最初の要素を残す。非破壊的な操作についてはseq-uniqを参照してください(シーケンスを参照)。

変数に格納されたリストへの要素の追加や、それを集合として使用する方法については、リスト変数の変更の関数add-to-listも参照してください。


Next: 連想リスト, Previous: 既存のリスト構造の変更, Up: リスト   [Contents][Index]