
コラム
AutoLISPで業務を効率化する 第四回【リスト操作関数 その1】

第三回では図形を操作する方法を解説しました。
LISPで図形を扱うという初歩的な内容が理解できたと思うので、今回からはより発展した内容を解説していこうと思います。
第四回と第五回でAutoLISPの「リスト」の操作関数について詳しく説明し、第六回はリストそのものを深堀する予定です。
リストとは
前回のおさらいを兼ねて、一般的に「リスト」と呼ばれるものについて簡単に解説します。
リストは公式に「関連する一連の値をスペースで区切り、括弧で囲んだもの」「複数の関連する値を格納できるもの」として説明されています。
リストは複数の要素を入れておける箱

変数は「何でも1つだけ入れておける箱」、選択セットは「図形名を好きなだけ入れておける箱」、リストは「何でも好きなだけ入れておける箱」です。
変数は1つの箱なので要素は一つしか入りませんが、リストは箱を好きな数用意できるので、複数の要素を格納できます。厳密に言えばリストは2つの箱なのですが、この点に関しては第六回で解説予定です。
ただ、変数は名前を付けてしばらく置いておけるのに対して、リストはその場での計算が終わると消えてしまいます。リストを繰り返し使いたい時は、変数にいれて保持しましょう。
■例:リストを変数に代入する
(setq lst ‘(a b c))
※リストはlistを略してlstという変数名がつけられることが多いです。
最小要素アトム
LISPでは、リストではない要素(値や文字列など)のことを「アトム」と言います。文字通り原子の様なイメージを持ってもらえたらよいです。リストという箱にある中身のことなので、リストは構造であり、アトムは実体であると言い換えることもできますね。ちなみに関数もアトムの一つで、シンボルアトムと呼ばれています。
リストを操作する関数
リスト操作関数に関しては、AutoCAD公式の「リスト操作関数リファレンス(AutoLISP)」にて網羅されています。
リストの要素を取り出す【car・cdr・nth関数】
まずは、car関数とcdr関数について説明します。
car関数はリストの先頭の要素をリストから取り出して取得し、cdr関数はリストの先頭以外の要素をリストごと取得します。

つまり、リストの先頭以から2番目の値が欲しい時は、一度cdr関数で先頭を取り除いてからcar関数で取り出さなくてはなりません。
■例:リスト(A B C)からBを取り出す
(car (cdr '(A B C)))
※「’」クォートについては後述
ちなみに、cdrとcarは最大4回まで省略して記述することができます。
(cddadr '(A (B C D)))
→(D)
リストの先頭をcar部、その次をcdr部と呼びます。car・cdr関数の名前の由来ですが、これについては第六回で詳しく解説します。
nth関数はリストのn番目の要素を取り出すことができます。
リストはインデックス番号で管理されています。インデックス番号は0から始まるため、例えば'(A B C)というリストがあった場合、先頭要素のAを取得したいならインデックス番号は0にしなくてはなりません。全体的に数字が1少なくなるので気を付けましょう。
■例:リスト(A B C)から2番目のBを取りだす
(nth 1 '(A B C))
リストを作る【quote・list関数】
quote関数は引数をそのまま戻り値として返します。

厳密にはリストを作るわけではなく、引数にリストを渡すとそのまま返すだけなので、「リストを引き渡す」ことができる関数とも言えます。引数は1つなので気を付けましょう。また、少し例外的な処理ですが、本来(quote 引数)と書くべきところを‘引数と省略することができます。
■例:リスト(0 1 2 3)を返す
(quote (0 1 2 3))
‘(0 1 2 3)※コマンドラインに直打ちする場合、括弧の外の「’」は認識されないので注意
list関数は文字通り、要素をまとめてリストにする関数です。

公式では「式を受け取り、結合して1つのリストにする」と紹介されていますが、これだと次のappend関数との違いがわかりにくいので、ここでは「リストを作る」と表現しています。
先ほどのquote関数を使う場合、計算や式を含んだリストであっても、そのまま出力されてしまいます。
(quote (0 1 (+ 2 3) 4))
→(0 1 (+ 2 3) 4))
しかしlist関数を使うと、リスト内の式を評価(実行)した上でリストを返してくれます。
(list 0 1 (+ 2 3) 4)
→(0 1 5 4)
複数のリストを結合する【append関数】
append関数は複数のリスト同士を結合することができます。

公式ではリストに値を追加することができる関数として紹介されていますが、このまま覚えるとミスを起こしやすいです。というのも、list関数の引数は何でもよかったのに対して、この関数の引数は全てリストでなくてはなりません。
例えば、リスト(A B C)にDを追加する場合、「値」を結合するのだからと、(append (A B C) D)としてはいけません。
正しくは、
(append '(A B C) '(D))
前述のquote関数やlist関数を使って、リストとして引数に与える必要があります。ちなみに、(append (A B C) (D))と記述しそうになりますが、これだと構文エラーです。このエラーが起こるのはAutoCAD側がLISP式とリストの区別がつかないからなのですが、詳しいことは第六回で説明いたします。
リストの要素を更新する【subst関数】
subst関数はリスト内の要素を書き換えることができます。

前回は図形定義データの任意の要素を編集するのに使用しましたね。書き換えは該当の全ての要素が対象になるので気をつけましょう。
■例: リスト(0 1 0 1)の0を1に書き換える
(subst 1 0 '(0 1 0 1))
→(1 1 1 1)
その他【last・length・member・reverse関数】
使用頻度は低くないのですが、取り立てて語ることもない関数はその他としてまとめました。
last関数は文字通りリストの最後の要素を取り出します。
(last '(A B C))
→C
length関数はリスト内の要素の数を返します。最大のインデックス番号ではありません。リストの中のリストは1でカウントされます。その中の要素数はカウントしません。
(length '(A B C (D E)))
→4
member関数は指定された要素がリスト内にあるかを検索し、初めに検出した以降の式を返します。
(member 'C '(A B C (D E)))
→(C (D E))
指定された要素は引数のリスト内の要素と完全一致する必要があります。つまりリストの中のリストの要素を指定しても判定しません。
(member 'D '(A B C (D E)))
→nil
reverse関数はリスト内の要素の順番を反転します。リストの中のリストは反転しません。
(reverse '(A B C (D E)))
→((D E) C B A)
まとめ
今回は、リストを操作する関数のいくつかを説明しました。次回は図形定義データの処理や、foreach、lambda等のリストを使った少し複雑な関数についても触れてみようと思います。
用語まとめ
最後に、今回解説した用語と関数をまとめて締めとさせていただきます。
|
名前 |
内容 |
|
car部 |
リストの先頭の要素 |
|
cdr部 |
リストの2番目の要素 |
|
アトム |
リストではない最小要素 |
|
関数名 |
内容 |
構文 |
例文 |
|
car |
リストの先頭の要素を返す |
(car リスト) |
(car (cons ‘A ‘B))→A |
|
cdr |
リストの先頭の要素を省いたリストを返す |
(cdr リスト) |
(cdr ‘(A B C))→(B C) |
|
nth |
リストのn番目の要素を返す |
(nth リスト) |
(nth 1 ‘(A B C))→B |
|
quote |
引数をそのまま返す |
(quote 要素)又は、’要素 |
(quote a)又は、’a→A |
|
list |
引数を評価(処理)してからリストとして返す |
(list 要素1 要素2 …) |
(list ‘A ‘(B) ‘C)→(A (B) C) |
|
append |
複数のリストを結合したリストを返す |
(append リスト1 リスト2) |
(append ‘(A B) ‘(C))→(A B C) |
|
subst |
リストの要素を更新して返す |
(subst 新要素 旧要素 リスト) |
(subst 0 1 ‘(0 1 0 1))→(0 0 0 0) |
|
last |
リストの最後の要素を返す |
(last リスト) |
(last ‘(A B C))→C |
|
length |
リストの要素の数を返す |
(length 関数) |
(length ‘(A B (C D)))→3 |
|
member |
指定要素をリストから検索し、検出した以降のリストを返す |
(member 指定要素 リスト) |
(member B ‘(A B C))→(B C) |
|
reverse |
リストの要素の順番を反転して返す |
(reverse リスト) |
(reverse ‘(A B (C D)))→((C D) B A) |