#

如果一個字串使用空白字元將資料隔成多個項目,例如:"apple book car duck",像這種格式的字串內容,Tcl稱之為清單(List)。對於清單式的資料Tcl提供了很多方便的操作命令,讓你可以快速的排序、搜尋及取出清單中項目。本篇文章介紹Tcl裡常用的清單命令並示範它們的使用方法。

6.1 建立清單

前面有說到清單是以空白當分隔的字串,所以你還是可以把清單當成是字串,只是Tcl對這種清單式的字串提供了額外的功能,讓你可以很容易的以項目為單位來操作這種資料,而不是以字元為單位。下面的程式展示了三種建立清單的方法,第一種使用雙引號來包夾字串,它總共隔出了3個項目。第2種改採用大括號來包夾字串,然後隔出了4個項目。最後一種使用list命令及命令代換來建立清單。



原則上你可以任意的使用上面的三種方法來建立清單,但要注意使用大括號會取消代換的功能,所以如果你有變數需要當成清單的項目,請考慮使用另外兩種方法,不然變數的內容不會被代換。例如下面的$var不會被代換。



如果項目本身也有包含空白,請用雙引號或大括號包夾項目,例如:



最後請特別注意,下面的程式是一個常見的錯誤,第2行你可能預期list1包含了4個項目,但其實包含了5個。因為根據變數代換的原則,第2行的$var被代換後,字串的結果是"pen pencil eraser pencil case",所以list1事實上包含了5個項目。



以下是比較正確的方法:



§ 關於清單

雖然上述的三種方法都可以用來建立清單,而且使用上的感覺也都一樣,但是實際上使用list命令建立的清單,Tcl內部會以不一樣的方法處理。所以如果你可以確定新建立的清單,不會被自己拿來當字串使用,請盡可能使用list命令,因為這樣會比較有效率。 以前我都叫清單為「串列」因為這樣比較符合Tcl內部的資料結構,不過後來覺得就字面上來說「清單」好像也滿貼切的,所以就都用清單了。

6.2 取出清單中的項目

Tcl提供了「索引」及「範圍」兩種方法來取出清單中的項目,「索引」的方法可以用來取出1個項目,而「範圍」的方法則可以取出項目的子集合。

6.2.1 取出清單中的單一項目

lindex命令可以用來取出清單中特定的項目,它的語法如下:

lindex list ?index?

lindex執行後回傳符合索引位置的項目。其中list是要操作的清單,index是整數的索引位置。如果不指定index的話會回傳所有的項目。程式6-1示範lindex常見的用法。程式的第1行先建立了一個3個項目清單,第2行用lindex命令取出$list中索引值是0的項目。注意哦!!清單的索引值由0開始算,所以取出來的項目是pen。第3行取出索引為2的項目,所以輸出是eraser,第4行說明lindex允許使用end來表示最後一個索引值,第5行則是由最後一個索引值往前算2個,所以是倒數第3個項目。



程式輸出:

pen
eraser
eraser
pen

6.2.2 取出清單的子集合

lrange命令可以用來取出清單中特定範圍的項目群,它的語法如下:
lrange list first last

lrange執行後會回傳取出一個範圍的項目群,然後回傳一個新的清單。list是要操作的清單,first是要取出的開始位置,last是要取出的結束位置。如同index命令first及last必需是零以上的整數,而且可以使用end來表示最後一個項目的索引值。如下是它的使用範例:



程式輸出:

apple book cute duck
duck eat fruit green
apple book cute duck eat fruit green
cute duck eat
eat fruit green

6.3 把項目加到已存在的清單

如果要把新的項目加入已存在的清單,可以使用linsert及lappend這兩個命令。lappend可以把新的項目附加在清單的尾巴。而linsert可以把新的項目插入清單的任意位置。

6.3.1 附加項目至清單的尾巴

lappend可以用來把新的項目附加至清單變數的尾巴,lappend的語法如下:

lappend varName ?value value value ...?

lappend把value的值逐一附加在varName的尾巴,最後回傳附加後的結果。varName必需是一個變數的名稱,如果變數不存在lappend會自動建立。如果沒有指定任何value則不附加任何項目。以下是lappend的使用方法:



程式輸出如下:

pen pencil
pen pencil eraser {pencil case}

6.3.2 插入項目至清單的任意位置

lappend有兩個特點:

  1. 只能用在清單變數上。
  2. 只能把新的項目串接在清單的最尾巴。

linsert和lappend不同,它可以把新的項目插入到清單的任意位置,下面是它的語法:

linsert list index element ?element element ...?

linsert執行後把項目element逐一插入清單list索引值為index的位置,然後回傳插入後新的清單。請注意linsert是對清單的值操作而不是對清單變數操作,所以它不會修改到變數的內容。以下是linsert示範用法:



程式輸出如下:

pen pen2 pencil eraser
pen pencil eraser
pen pen2 pen3 pencil eraser

linsert同樣可以使用end來表示最後一個項目的索引值。特別注意!! 執行linsert並不會修改到清單變數。所以從程式第3行的輸出可以發現,$list1並沒有因為第2行的程式而被改變。第4行把linsert執行的結果重新設定給list1變數,所以第5行的輸出可以看出list1變數被改變了。

6.4 其它常用的清單操作命令

接下來我們要繼續測試幾個常用的清單命令,包含計算項目數量用的llength、排序用的lsort及搜尋用的lsearch。

6.4.1 計算清單包含的項目數量

如果你想知道清單到底包含幾個項目可以使用如下的llength命令:



程式輸出如下:

3

6.4.2 排序清單中的項目

lsort排序清單中所有的項目,並回傳排序後新的清單,它的語法如下:

lsort ?options? list

list是要被排序的清單,options欄位用來調整排序時的方法,以下是options欄位常用的參數:

表6-1 lsort可用的選項
-ascii
使用Unicode內部的編碼來排序,這是預設的方法。
-dictionary
使用像字典一樣的排序方式。
-integer
把所有清單中的項目轉換為整數排序。
-real
把所有清單中的項目轉換為浮點數排序。
-command command
使用自己提供的命令來比較清單的內容,lsort會不斷執行command命令並把2個項目傳入,如果第1個項目大於第2個command需要回傳1,如果2個項目相同command需要回傳0,如果第1個項目小於第2個項目command要回傳-1。
-increasing
排序的結果使用遞增的方式,這是預設的方法。
-decreasing
排序的結果使用遞減的方式。
-index index1
如果指定這個參數,每一個項目的內容都會被當成是子清單,然後lsort會對每個子清單索引位置為index1的項目做排序。
-nocase
排序時把英文字母大小寫當作一樣。
-unique
找出清單裡最長且不重複的子清單集合。

它的示範如下:



程式輸出如下:

apple book cute duck eat fruit green
green fruit eat duck cute book apple
a1 a10 a100
1 2 3 4 5 11
1 2 3 4

6.4.3 搜尋清單中的項目

lsearch命令可以用來搜尋清單中符合關鍵字的項目,並回傳第一個找到的索引位置。它的語法如下:

lsearch ?options? list pattern

lsearch傳回清單list中第一個符合pattern的項目索引值,如果找不到符合的項目就回傳-1。其中list是目標要搜尋的清單,pattern是要搜尋的關鍵字,options可以用來指定搜尋時的方法。以下是options欄位常用的參數:

表6-2 lsearch可用的選項
-all
如果指定這個參數lsearch會找出所有符合索引的位置,並把位置以清單的型式回傳。
-ascii
先把清單項目使用Unicode內部的編碼來排序,然後再執行搜尋動作。
-decreasing
先把清單做遞減排序,然後再執行搜尋動作。
-dictionary
先把清單做字典方式排序,然後再執行搜尋動作。
-exact
使用精確比對。
-glob
使用unix glob方式的比對,這是預設值。
-increasing
先把l清單做遞增排序,然後再執行搜尋動作。
-inline
回傳時改用符合的項目內容取代符合的項目索引,如果配合-all,會回傳所有符合的項目清單。
-integer
把所有的項目轉成整數來排序,然後再執行搜尋動作。
-not
反相搜尋,找出第一個不符合pattern的項目。
-real
把所有的項目轉成浮點數型態來排序,然後再執行搜尋動作。
-regexp
使用正規表示式比對。
-sorte
讓lserch在搜尋前跳過排序的動作,並使用exact方式比對。
-start
指定啟始的搜尋位置。

lsearch示範使用如下:



程式輸出如下:

2
2 5
b35
a20
a20 c47
0 2
5

本章回顧

如果一個字串使用空白字元將字串隔成多個項目,像這種格式的字串內容,Tcl稱之為清單(List)。對於清單式的資料Tcl提供了很多方便的操作命令,讓你可以快速的排序、搜尋及取出清單中項目。建立清單的方法像這樣:



常用來操作清單的命令整理如下:

命令 說明
lappend varName ?value value value ...? lappend把value的值逐一附加在varName的尾巴,最後回傳附加後的結果。varName必需是一個變數的名稱。
lindex list ?index? lindex取出list索引位置index的項目。
insert list index element ?element element ...? linsert把項目element逐一插入list索引值為index的位置,然後回傳插入後新的清單。
lrange list first last lrange取出list範圍first到last的項目群,然後回傳新的清單。
lsearch ?options? list pattern lsearch傳回list中第一個符合pattern的項目索引值,如果找不到符合的項目就回傳-1。
lsort ?options? list lsort排序list中所有的項目,並回傳排序後新的清單。

Theme Design by devolux.org. Converted by Wordpress To Blogger for WP Blogger Themes. Sponsored by iBlogtoBlog
This template is brought to you by : allblogtools.com | Blogger Templates