0 回顾
列表part0和part1描述了列表的创建,修改,获取,搜索等相关命令。接下来这篇文章将介绍列表的排序和拼接。通过这三篇文章的描述,详细大家对列表具有一个详细并且系统的认识。
1 排序
排序是一个老生常谈的话题。最最最常见的排序方式就是升序,降序,unique以及字典等。下面将挨个介绍。
-
lsort命令格式
lsort <options> list0
该命令实现列表list0元素排序的功能。其中,option表示命令lsort包含的选项,一般以“-”开头。常见的option包含:-decreasing,-increasing,-unique, -directionary(非常常用的一个选项),-integer,-real。 它们分别表示降序,升序,唯一,字典,整数(从小到大)和浮点数(从小到大);list0表示列表本身,而不是列表名称。- decreasing表示列表中的元素从大到小排列
- increasing表示列表中的元素从小到大排列
- unique表示删除队列中重复的元素
- directionray表示按照字典(数字>小写字母(a-z)>大写字母(A-Z),其中数字从小到大,通常用于文件的排序)的方式对列表中的元素进行排序
- integer表示列表的元素按照从小到大的方式排列,排列的对象只能是整数
- real表示列表的元素按照从小到大的方式排列,排列的对象是浮点数或者整数。(整数1也可以认为是浮点数1.0)
-
基础示例
# Example1 # 创建列表x_list0 set x_list0 [list John Anne Mary Jim] # 列表x_list0按照降序排列其中的元素 lsort -decreasing $x_list0 # 结果:Mary John Jim Anne# Example2 # 列表x_list0按照升序排列其中的元素 lsort -increasing $x_list0 # 结果: Anne Jim John Mary# Example3 # 创建列表x_lsit0 set x_list0 [list B a C 10 2] # 列表x_lsit0按照升序排列其中的元素 lsort -increasing $x_list0 # 结果: 10 2 B C a# Example4 # 创建列表x_list1 set x_lsit1 [list apple Banana Zebra 123] # 列表x_list1按照字典的方式排列其中的元素 lsort -dictionary $x_lsit1 # 结果:123 apple Banana# Example5 # 创建列表x_list1 set x_list1 [list n1.gif n10.gif n9.gif n11.gif] lsort -dictionary $x_lsit2 # 结果: n1.gif n9.gif n10.gif n11.gif# Example6 # 创建列表x_list2 set x_lsit2 [list apple Banana Zebra apple] # 删除列表x_list2中重复的元素 lsort -unique $x_list2 # 结果:apple Banana Zebra# Example7 # 创建列表x_list3 set x_list3 [list 100 5 20] # 列表x_lsit3按照整数的方式从小到大 lsort -integer $x_list # 结果:5 20 100# Example8 # 创建队列x_list4 set x_list4 [list 100 5.23 20.10] lsort -real $x_list4 # 结果: 5.23 20.10 100
-
解析
Example1~3展示了increasing和decreasing的基础示例。其中,Example3混合了数字和字母,该实例是想说,increasing和decreasing排序每次比较一个字符的ASCII码,若相同则比较下一个字符;直到两者不同为止。字母和数字对应的ASCII码如下所示:数字:0-9: 48-57 小写字母:a-z: 65-90 大写字母:A-Z: 97-122
这就很好的解释了Example3中为啥“10”会排在“2”的前面。ASIC或者FPGA的follow中通常需要将多个文件进行排序,为此increasing和decreasing就显得不那么友好,此时推荐使用dictionary。
Example8中100在排序时被当作100.0看待,即Tcl在排序前做了浮点类型的转换。
2 拼接
- split命令格式
split str0 str1
该命令将字符串str0根据分隔符str1进行切分,并且返回一个列表。或者说,split命令会找到字符串str0中所有的分隔符,返回一个列表,列表中的元素就是分隔符str1之间的元素。其中,分隔符可以是空字符,单个字符或者多个字符;str0是字符串变量,而不是字符串的名字;str1可以是字符串,或者字符串变量。可以分成三种情况理解:
- 若分隔符str1是空字符, 则字符串str0的所有字符都被切分,即使是空格。即空格也会被分成一个单一的字符。
- 若分隔符str1是单个字符,则字符串str0将被分隔符str1进行切分;切分后的部分组成一个列表。
- 若分隔符str1是多个字符,则只要字符串str0中有一个字符和分隔符str1中的字符匹配,则字符串str0被切分一次;若连续两个字符都和分隔符匹配(分隔符挨个匹配),则进行连续切分,获得一个空字符;最终切分的元素返回一个列表。
-
基础示例
# 创建字符串x_str0 set x_str0 xbaybz set x_str1 {} split $x_str0 $x_str1 # 结果:x b a y b z# 创建分隔符,并且分隔符是单个字符 set x_str1 b split $x_str0 $x_str1 # 结果:x ay z# 创建分隔符,并且分隔符多个字符 set x_str1 ab split a {} y z
-
解析
第一个实例中分隔符是空字符,因此,x_str0中的所有元素都将被切分。
第二个实例中分隔符是单个字符。字符串xbaybz将被分隔符b切分,切分后的部分组成一个列表,列表的元素为字符串切分后的各个部分。
第三个实例中分隔符是多个字符。字符串xbaybz将被分隔符ab切分。同学们看到这个结果可能会很意外。其实很简单,我们把多个分隔符拆成多个单字符的分隔符就可以了。如本实例中,分隔符为“ab”,那咱们就看成两个分隔符,分别为分隔符a和分隔符b。在切分过程中,字符串xbaybz同时和分隔符a,分隔符b进行匹配。只要其中一个匹配,则进行切分,随后进入下一个字符的比较。详细流程如下所示:
step1: 字符串中的第一个字符x和分隔符a进行匹配,发现不匹配;随后进行字符x和分隔符b进行匹配,发现不匹配。进入step2;
step2: 字符b和分隔符a不匹配,随即进行字符b和分隔符b进行匹配,此时匹配成功,进行切分。故列表的第1个元素是x。进入step3;
step3: 字符a和分隔符a进行匹配,匹配成功,进行切分。此时获得一个空元素。故列表的第2个元素是一个空字符串。进入step4;
step4…
最终,列表的元素为: a {} y z。 -
join命令格式
join list0 str0
该命令可以理解为split命令的逆操作。将列表lsit0中的各个元素按照分隔字符串str0进行拼接,最终获得一个字符串。其中,分隔字符串可以是任意多个字符串,包括空字符串。另外值得说明的是,list0和str0都是变量,而不是变量名称。 -
基础示例
# 创建列表x_list0 set x_list0 [list {} usr include sys types.h] # 创建分隔字符串 set split_str0 "/" join $x_list0 $split_str0 # 结果: /usr/include/sys/types.h# 创建列表x_list1 set x_list1 [list 24 112 5] # 创建分割字符串 set split_str1 "+" expr [join $x_list1 $split_str1] # 结果:141
-
解析
第一个实例实现了文件路径的拼接,为了实现usr前面带一个“/”,待拼接的列表x_list0需要包含一个空元素。即可以实现usr作为根目录。
第二个实例实现列表数字的累计,是一个较为特殊的用法。该实例中,首先将列表的元素按照分割字符串“+”进行拼接;随后将拼接好的字符串传入expr;最后经过expr的计算,获得最终的结果。