Next: Property Lists, Previous: Sets And Lists, Up: Lists [Contents][Index]
連想配列(association list、短くはalist)は、キーと値のマッピングを記録します。これは連想(associations)と呼ばれるコンスセルのリストです。各コンスセルにおいてCARはキー(key)で、CDRは連想値(associated value)となります。3
以下はalistの例です。キーpine
は値cones
、キーoak
はacorns
、キーmaple
はseeds
に関連付けられます。
((pine . cones) (oak . acorns) (maple . seeds))
alist内の値とキーには、任意のLispオブジェクトを指定できます。たとえば以下のalist0では、シンボルa
は数字1
、文字列"b"
はリスト(2
3)
(alist要素のCDR)に関連付けられます。
((a . 1) ("b" 2 3))
要素のCDRのCARに連想値を格納するようにalistデザインするほうがよい場合があります。以下はそのようなalistです。
((rose red) (lily white) (buttercup yellow))
この例では、red
がrose
に関連付けられる値だと考えます。この種のalistの利点は、CDRのCDRの中に他の関連する情報
— 他のアイテムのリストでさえも —
を格納することができることです。不利な点は、与えられた値を含む要素を見つけるためにrassq
(以下参照)を使用できないことです。これらを検討することが重要でない場合には、すべての与えられたalistにたいして一貫している限り、選択は好みの問題といえます。
上記で示したのと同じalistは、要素のCDRに連想値をもつと考えることができます。この場合、rose
に関連付けられる値はリスト(red)
になるでしょう。
連想リストは新しい連想値を簡単にリストの先頭に追加できるので、スタックに保持したいような情報を記録するのによく使用されます。連想リストから与えられたキーにたいして連想値を検索する場合、それが複数ある場合は、最初に見つかったものがreturnされます。
Emacs Lispでは、連想リストがコンスセルでなくても、それはエラーではありません。alist検索関数は、単にそのような要素を無視します。多くの他のバージョンのLispでは、このような場合はエラーをシグナルします。
いくつかの観点において、プロパティーリストは連想リストと似ていることに注意してください。それぞれのキーが一度だけ出現するような場合、プロパティーリストは連想リストと同様に振る舞います。プロパティーリストと連想リストの比較については、Property Listsを参照してください。
この関数は、alist要素にたいしてkeyを比較するのにequal
を使用して、alist内からkeyをもつ最初の連想をリターンする。CARがkeyとequal
であるような連想値がalistになければ、この関数はnil
をリターンする。たとえば:
(setq trees '((pine . cones) (oak . acorns) (maple . seeds))) ⇒ ((pine . cones) (oak . acorns) (maple . seeds)) (assoc 'oak trees) ⇒ (oak . acorns) (cdr (assoc 'oak trees)) ⇒ acorns (assoc 'birch trees) ⇒ nil
以下はキーと値がシンボルでない場合の例である:
(setq needles-per-cluster '((2 "Austrian Pine" "Red Pine") (3 "Pitch Pine") (5 "White Pine"))) (cdr (assoc 3 needles-per-cluster)) ⇒ ("Pitch Pine") (cdr (assoc 2 needles-per-cluster)) ⇒ ("Austrian Pine" "Red Pine")
関数assoc-string
はassoc
と似ていますが、文字列間の特定の違いを無視する点が異なります。Text Comparisonを参照してください。
この関数はalistの中から値valueをもつ最初の連想をリターンする。CDRがvalueとequal
であるような連想値がalistになければ、この関数はnil
をリターンする。
rassoc
はassoc
と似てイルが、CARではなくalistの連想値のCDRを比較する。この関数は与えられた値に対応するキーを探す、assoc
の逆バージョンと考えることができよう。
この関数は、alistからkeyをもつ最初の連想値をリターンする点はassoc
と同様だが、比較にequal
ではなくeq
を使用する点が異なる。CARがkeyとeq
であるような連想値がalist内に存在しなければ、assq
はnil
をリターンする。eq
はequal
より早く、ほとんどのalistはキーにシンボルを使用するので、この関数はassoc
より多用される。Equality Predicatesを参照のこと。
(setq trees '((pine . cones) (oak . acorns) (maple . seeds))) ⇒ ((pine . cones) (oak . acorns) (maple . seeds)) (assq 'pine trees) ⇒ (pine . cones)
逆にキーがシンボルではないalistでは、通常はassq
は有用ではない:
(setq leaves '(("simple leaves" . oak) ("compound leaves" . horsechestnut))) (assq "simple leaves" leaves) ⇒ nil (assoc "simple leaves" leaves) ⇒ ("simple leaves" . oak)
この関数はassq
と似ているが、keyにたいする連想値全体(key
.
value)
ではなく、valueだけをリターンする点が異なる。keyがalist内で見つからなければdefaultをリターンする。
これはsetf
での値の変更に使用できる汎変数である(Generalized Variablesを参照)。値の値へのセットにこれを使用する際、オプション引数removeが非nilの場合は、新たな値がdefaultとeql
なら、alistからkeyを削除することを意味する。
この関数は、alist内から値valueをもつ最初の連想値をリターンする。alist内にCDRがvalueとeq
であるような連想値が存在しないならnil
をリターンする。
rassq
はassq
と似ていますが、CARではなくalistの各連想のCDRを比較します。この関数を、与えられた値に対応するキーを探すassq
の逆バージョンと考えることができます。
たとえば:
(setq trees '((pine . cones) (oak . acorns) (maple . seeds))) (rassq 'acorns trees) ⇒ (oak . acorns) (rassq 'spores trees) ⇒ nil
rassq
は要素のCDRのCARに保管された値の検索はできません:
(setq colors '((rose red) (lily white) (buttercup yellow))) (rassq 'white colors) ⇒ nil
この場合、連想(lily
white)
のCDRはwhite
ではなくリスト(white)
です。これは連想をドットペア表記で記述すると明確になります:
(lily white) ≡ (lily . (white))
この関数は、keyにたいするマッチをalistから検索する。alistの各要素にたいして、この関数はkeyと要素(アトムの場合)、または要素のCAR(コンスの場合)を比較する。比較はtestに2つの引数
— 要素(か要素のCAR)とkey —
を与えて呼び出すことにより行なわれる。引数はこの順番で渡されるので、正規表現(Regexp Searchを参照)を含むalistでは、string-match
を使用することにより有益な結果を得ることができる。testが省略またはnil
なら比較にequal
が使用される。
alistの要素がこの条件によりkeyとマッチすると、assoc-default
はその要素の値をリターンする。要素がコンスなら値は要素のCDR、それ以外ならリターン値はdefaultとなる。
keyにマッチする要素がalistに存在しないければ、assoc-default
はnil
をリターンする。
この関数は深さのレベルが2のalistのコピーをリターンする。この関数は各連想の新しいコピーを作成するので、元のalistを変更せずに新しいalistを変更できる。
(setq needles-per-cluster '((2 . ("Austrian Pine" "Red Pine")) (3 . ("Pitch Pine"))
(5 . ("White Pine")))) ⇒ ((2 "Austrian Pine" "Red Pine") (3 "Pitch Pine") (5 "White Pine")) (setq copy (copy-alist needles-per-cluster)) ⇒ ((2 "Austrian Pine" "Red Pine") (3 "Pitch Pine") (5 "White Pine")) (eq needles-per-cluster copy) ⇒ nil (equal needles-per-cluster copy) ⇒ t (eq (car needles-per-cluster) (car copy)) ⇒ nil (cdr (car (cdr needles-per-cluster))) ⇒ ("Pitch Pine")
(eq (cdr (car (cdr needles-per-cluster))) (cdr (car (cdr copy)))) ⇒ t
以下の例は、どのようにしてcopy-alist
が他に影響を与えずにコピーの連想を変更可能なのかを示す:
(setcdr (assq 3 copy) '("Martian Vacuum Pine")) (cdr (assq 3 needles-per-cluster)) ⇒ ("Pitch Pine")
この関数は、delq
を使用してマッチする要素を1つずつ削除するときのように、CARがkeyとeq
であるようなすべての要素をalistから削除する。この関数は短くなったalistをリターンし、alistの元のリスト構造を変更することもよくある。正しい結果を得るために、alistに保存された値ではなくassq-delete-all
のリターン値を使用すること。
(setq alist '((foo 1) (bar 2) (foo 3) (lose 4))) ⇒ ((foo 1) (bar 2) (foo 3) (lose 4)) (assq-delete-all 'foo alist) ⇒ ((bar 2) (lose 4)) alist ⇒ ((foo 1) (bar 2) (lose 4))
この関数は、alistからCDRがvalueとeq
であるようなすべての要素を削除する。この関数は短くなったリストをリターンし、alistの元のリスト構造を変更することもよくある。rassq-delete-all
はassq-delete-all
と似ているが、CARではなくalistの各連想のCDRを比較する。
ここでの“キー(key)”の使い方は、用語“キーシーケンス(key sequence)”とは関係ありません。キーはテーブルにあるアイテムを探すために使用される値という意味です。この場合、テーブルはalistでありalistはアイテムに関連付けられます。
Next: Property Lists, Previous: Sets And Lists, Up: Lists [Contents][Index]