リストを作成・更新するコマンドは、list, lrepeat, lappend, concat, lsetがあります。この記事は、リストの作成・更新に関連するコマンドを紹介します。
リストについて
[リストのデータ構造]
Tclのリストは複数の要素を空白で区切ったデータ構造をしています。各要素は0から始まるindex番号で管理しています。
例.りんご みかん バナナ
単純なリストであれば、直接書くことも出来ますが、空白を含む要素や、二重構造(入れ子(ネスト))になった複雑な構造を持ったリストを生成する場合には、リスト関連のTclコマンドを使用した方が楽に生成できます。
Tclコマンドを使って生成すれば、クォートに関する処理が自動的に行われ、正しいリストを得ることができます。
リストの作成 - listコマンド –
[書式]
list ?arg arg ...?
listコマンドは引数で指定した要素のリストを生成して返します。
[使用例1]
% set x {10 20 30} ----(1)
10 20 30
% set l1 [list 10 20 30] ----(2)
10 20 30
[説明]
(1)要素が3つのリスト
setコマンドで空白区切りの文字列を{}でグループ化したもの。10 20 30 が、それぞれ1つの要素です。
(2) 要素が3つのリスト
(1)と同じリストをlistコマンドで作成したもの。
例のような単純なリストであれば、listコマンドを使用しなくても間違えずに直接リストを書くことができます。
[使用例2]
% set x {10 20 30}
10 20 30
% set y hello
hello
% set l2 [list $x "a b c" $y] ----(1)
{10 20 30} {a b c} hello
% set l3 "\{$x\} {a b c} $y" ----(2)
{10 20 30} {a b c} hello
[説明]
(1) 要素が3つのリスト。
$xの変数置換された10 20 30 が1つの要素です。listコマンドが自動的に{}でグループ化を行います。次の要素は””でグループ化された a b c が1つの要素です。listコマンドはリストの要素のグループ化に{}を使います。
(2) 要素が3つのリスト
(1)をlistコマンドを使用せずにリストを作成すると「{ }」を「\」でクォートするなどの処理が必要になってきます。
要素を繰り返したリストを作成 – lrepeatコマンド –
[書式]
lrepeat number element1 ?element2 element3 ...?
lrepeatコマンドは、要素を繰り返したリストを作成します。
[使用例]
% lrepeat 3 abc
abc abc abc
% lrepeat 3 a b c
a b c a b c a b c
% lrepeat 3 [lrepeat 3 0]
{0 0 0} {0 0 0} {0 0 0}
リストの末尾に要素を追加する – lappendコマンド –
[書式]
lappend varName ?value value value ...?
lappendコマンドは、第1引数で指定した変数に要素を追加します。未定義の変数名を指定すると、第2引数以降で指定した要素をもつリストを新しく作成します。
[参考]
appendの意味:添える。付加する。追加する。
[使用例]
% set num {10 20 30}
10 20 30
% lappend num 40 50 ----(1)
10 20 30 40 50
% set num
10 20 30 40 50
% set str "yellow green"
yellow green
% lappend new red blue $str ----(2)
red blue {yellow green}
[説明]
(1) 要素を追加する
変数num に40 50 を追加する。
(2) 未定義の変数名を指定する
未定義の変数名を指定すると、第2引数以降で指定した要素をもつリストを作成します。変数newは、red blue {yellow green}の3つの要素をもつリストになります。
複数のリストを連結する – concatコマンド –
[書式]
concat ?arg arg ...?
concatコマンドは、すべての引数をまとめて、1つの新しいリストを作成します。値は要素またはリストを指定する。
[使用例]
% set x {10 20 30}
10 20 30
%set y {40 50}
40 50
%set z 60
% set var1 [concat $x $y $z 70 80] ----(1)
10 20 30 40 50 60 70 80
% set var2 [list $x $y $z 70 80] ----(2)
{10 20 30} {40 50} 60 70 80
% set var3 [concat 10 20 $z] ----(3)
10 20 60
[説明]
(1) リストを連結する
concatコマンドは、与えられた、すべての引数(変数x,y,zのリストと70,80)をスペースで連結し、1つの新しいリストを生成します。
(2) listとconcatの違い
listやlappendはリスト構造を保持するのに対し、concatはリスト構造のレベルを1段階取り除きます。
(3)
listとconcatは、扱うデータによっては同じ結果を返す場合もあります。(3)はlistコマンドでも同じ結果を返します。
しかし、同じ結果を返すことを利用した書き方は避けるべきです。例えば、変数zの値が{60 70}に変化すると違った結果になり、バグを生む恐れがあります。
concatコマンドは、生成されるリスト構造が、listコマンドやlappendコマンドとは違うことを意識する必要があります。
リストの要素を変更する – lsetコマンド –
[書式]
lset varName ?index...? newValue
lsetコマンドは、指定したindexの要素を変更します。indexを省略した場合、varNameの値を新しい値に上書きします。indexは入れ子になったリストの要素も指定できます。
[使用例1]
% set num {10 20 30 40 50 60}
10 20 30 40 50 60
% lset num 2 80 ----(1)
10 20 80 40 50 60
% lset num abc ----(2)
abc
[説明]
(1)指定した要素を変更する
index 2 の値:30を80に変更します。
(2)指定した変数を新しい値に上書きする
indexを省略しているので変数numは値:abcで上書きされます。
[使用例2]
% set str1 {red blue}
red blue
% set str2 {yellow green}
yellow green
% set color [list $str1 $str2]
{red blue} {yellow green}
% lset color 1 1 black ----(1)
{red blue} {yellow black}
% set str {a b c {d e {f g h}}}
a b c {d e {f g h}}
% lset str 3 2 1 G -----(2)
a b c {d e {f G h}}
[説明]
indexは入れ子になったリストの要素も指定できます。
(1)
index 1のサブリストの中のindex 1 の値:green を black に変更します。
(2)
同じようにindex 3-2-1 の 値:g を G に変更します。
indexの指定は以下のように「{ }」で囲むこともできます
lset color {1 1} black
lset str {3 2 1} G
[使用例3]
% set x {10 20 30 40 50 60}
10 20 30 40 50 60
% lset x end 80 ----(1)
10 20 30 40 50 80
% lset x end-1 70 ----(2)
10 20 30 40 70 80
[説明]
(1)
indexに「end」を指定すると最後の要素を変更します。
(2)
「end-1」は最後から1つ手前の要素。end-整数」で最後から指定した整数値を引いた要素を示します。
[使用例4]
% set x {10 20 30}
10 20 30
% lset y {10 20 30} ----(1)
can not read "y": no such variable
% lset x 3 40 ----(2)
list index out of range
# 8.6の挙動 ----(3)
% lset x 3 40
10 20 30 40
% lset x 5 60
list index out of range
% lset x end+1 50
10 20 30 40 50
[説明]
(1)
未定義の変数を指定するとエラーになります。
(2)
指定したindexが要素数より大きいとエラーになります。
(3) 8.6の挙動
- 要素数より1つ大きいindexを指定すると要素が追加されます。
- 2つ以上大きいindexを指定するとエラーになります。
- indexに「end+1」が指定できます。
8.5では、(2)の挙動をします。
[参考]
Changed Tcl behavior
(変更されたTclの動作)・lset can now set the element at index end+1, growing the list. [TIP #331]
(lsetはindexのend+1に要素を設定し、リストを拡大することができます。)
Changes in Tcl/Tk 8.6 より抜粋
コメント