1. 概述所有Q中的数据类型最终都是由list构造的:一个字段(dictionary)是由一对list构造的;一个表是一个特殊的字典;一个键表(keyed table)是一对表。因此熟悉一下list还是很重要的。List支持索引取值,并且支持不同元素类型,可以把q list当作动态分配的数组。1. 简介1. 定义一个list是一个存储q data的有序容器,使用括号表示,并且使用分号来分割元素。q)(1; 1.1; 1)11.11q)(1;2;3)1 2 3q)(“a”;“b”;“c”;“d”)“abcd"q)(Life;the;Universe;and;Everything)LifetheUniverseandEverythingq)(-10.0; 3.1415e; 1b; abc; "z")-10f3.1415e1babc"z"q)((1; 2; 3); (4; 5))1 2 34 5q)((1; 2; 3); (1; "2"; 3); 4.4)1 2 3(1;“2”;3)4.4注意到没个的输出结果不太一样,第一个和最后三个是general list,意味着list中的元素非同质的。list同样可以被复制给变量:q)L1:(1;2;3)q)L2:(“z”;“a”;“p”;“h”;“o”;“d”)q)L3:((1; 2; 3); (1; "2"; 3); 4.4)2. countcount相当于length, 返回list中元素的个数, 类型为longq)count (1;2;3)3在q3中,list中元素最多有2^64-1个;在q2中,最多有20亿个。count也可以对atom进行操作,尽管它们不是list,但仍返回1:q) count 421类似于count的操作符还有first和last,返回list中第一个和最后一个元素。2. 简单listSimple list: 所有list中的元素都是同种类型的,这种列表具有很好的储存和性能(占据连续的储存空间)。You can always use general list notation, even for simple lists.当q检测到一个list中元素是同种类型的时候,它会自动地将list转换为简单list。1. 简单整型list对于任何数值类的List,在表示的时候,都可以忽略掉括号和分号,元素之间用空格隔开。q)(100;200;300)100 200 300q)100 200 300100 200 300q)100 200 300~(100; 200 ; 300)1bq)(1h; 2h; 3h)1 2 3h注意1 2 3h这种形式的表示,后缀h是作用在整个List的元素上,而(1;2;3h)中后缀h仅仅作用在最后一个元素上,该list是一个general list.q)(1; 2; 3h)123h2. 简单浮点型listq)123.4567 9876.543 99123.4567 9876.543 99q console压缩了小数部分为0的浮点数,上式中的99不是整型: 即当在一个float list中加入一个看似整型数字的时候,q会认为仅仅省略了数字右边的小数部分,因此你仍然得到的是一个简单浮点型list.3. 简单Binary list甚至可以省略空格符,boolean类型以后缀b结尾:q)(0b;1b;0b;1b;1b)01011bq)01011b01011bbyte类型以0x开头:q)(0x20;0xa1;0xff)0x20a1ffq)0x20a1ff~(0x20;0xa1;0xff)1bGUID类型与integer类型一样,以空格符分离q)3?0Ng8c6b8b64-6815-6084-0a3e-178401251b68 5ae7962d-49f2-404d-5aec-f7c8abbae288 5a5..4. 简单Symbol list中间没有空格分隔, 如果有空格会报错q)(Life;the;Universe;and;Everything)LifetheUniverseandEverythingq)LifetheUniverseandEverythingLifetheUniverseandEverythingq)bad news'bad5. 简单char list和Stringchar list的简化形式像许多语言中的string类型;事实上, char list被称为string,由于string是list类型,因此不能比较两个不同长度string的大小。q)("s"; "t"; "r"; "i"; "n"; "g")"string"q)"string""string"比较:q)"string"="text"'lengthq)"string"~"text"0b6. 时间类型list由于它们实际上是整型, 所以简化版本的simple list以空格符进行分隔:q)(2000.01.01; 2001.01.01; 2002.01.01)2000.01.01 2001.01.01 2002.01.01q)(00:00:00.000; 00:00:01.000; 00:00:02.000)00:00:00.000 00:00:01.000 00:00:02.000对于混合日期类型的list,所有元素的类型与第一个元素保持一致,可以追加一个类型指定符来指定list元素类型:q)12:34 01:02:0312:34:00 01:02:03q)01:02:03 12:34 11:59:59.999u01:02 12:34 11:593. 空和单例list1. 一般的空list以()或( )表示一个空list,其在q console中没有显示。可以使用-3!()来强制显示()。2. 单例list一个singleton表示一个只含有一个元素的list. 由于()除了用来生成列表外,还是数学表达式中的符号,单单使用(42)会得到元数据42,因此不可能用()来生成一个单例list.单例list用函数enlist来创建:q)enlist 42,42只带有一个元素的string不能够被写为"a",这只是一个character的元数据,应当使用enlist. This is a common error for qbies.q)“a"“a"q)enlist “a”, “a"注意单例并不一定要以atom作为它仅有的元素,它可以是任何q元素:q)enlist 1 2 31 2 3q)enlist (10 20 30; abc)10 20 30 a b c4. 索引1. 标识 以[i]的形式:q)(100; 200; 300)[0]100q)100 200 300[0]100q)L:100 200 300q)L[0]1002. 索引赋值q)L:1 2 3q)L[1]:42q)L1 42 3注意向简单list赋值的时候,赋值类型必须与list元素的类型保持一致,否则会报错。3. 索引域如果索引在合理的边界之外,结果不是一个错误,而会返回一个Null值,表示“missing data”, 返回的Null值类型与第一个元素的类型一致。q)L1:1 2 3 4q)L1[4]0Nq)L2:1.1 2.2 3.3q)L2[-1]0nq)L3:(1; 2; 3.3)q)L3[0W]4. 空索引和Null项一个忽略的索引返回整个list:q)L:10 20 30 40q)L[]10 20 30 40空索引与索引为空的list不同,后者会返回一个空的list,可以用指令-3!来强制显示q)-3!L[()]"()"双冒号::代表nil,即零(无)项,返list所有元素。q)L[::]10 20 30 40同时,在list中使用::可以避免general list在被转换为simple list之后,无法再赋值的情况,具体见下例:q)L:(::; 1 ; 2 ; 3; a)q)L[4]:4q)L[4]:a5. 合并list1. , join 逗号连接符,右边的list被拷贝到一个左边list的拷贝上,join同时支持atom,即支持作用于单元素。q)1 2 3,4 51 2 3 4 5q)1,2 3 41 2 3 4q)1 2 3,41 2 3 4可以使用(), x或者x, ()来生成x的单元素list,效果等同于enlist x2. ^ merge另一种合并list的方法是,对于两个长度相等的list, 可以使用^对它们合并。其结果是右侧元素占据左侧元素,除非右侧元素为null值。q)L1:10 0N 30q)L2:100 200 0Nq)L1^L2100 200 306. list作为maplist将索引i映射到元素L[i]I O0 1 21 3 47. list 嵌套1. 深度list中的元素为list称为嵌套,嵌套的层数为深度depth, atom的depth是0, 简单list的depth为1.q)L:(1;2;(100;200))q)count L3 2. 图例 8. list 多重索引可以使用L[1][2][0]或者L[1;2;0](注意是分号)来读取元素,前者被称为iterated indexing,后者被称为index at depth。其中,index at depth方法可以赋值,但是iterated indexing不支持赋值操作:q)L:(1; (100; 200; (1000 2000 3000 4000)))q)L[1; 2; 0]: 999q)L(1; (100; 200; (999 2000 3000 4000)))q)L[1][2][0]:42'assign构造matrix的一个方法:Reshape操作符#,下面代码中的0N(missing data)类似于python中的-1q)2 0N#til 100 1 2 3 45 6 7 8 9q)0N 3#til 100 1 23 4 56 7 8,99. 使用list索引1. 提取多个元素我们可以使用简单list作为索引, 索引可以是任意顺序,甚至可以是重复的。q)L:100 200 300 400q)L[0 2]100 300q)L[0 2 0]100 300 1002. 通过变量索引q)L100 200 300 400q)I:0 2q)L[I]100 3003. 通过嵌套list索引返回的结果与嵌套索引list具有相同的shapeq)L:100 200 300 400q)L[(0 1; 2 3)]100 200300 4004. 通过索引list赋值 q)L[1 2 3]:2000 3000 4000赋值操作是按照从左到右的顺序进行的q)L[3 2 1]:999 888 777is equivalent to,q)L[3]:999q)L[2]:888q)L[1]:777因此,如果对重复项进行赋值的时候,最右边的项被保留下来。q)L:100 200 300 400q)L[0 1 0 3]:1000 2000 3000 4000q)L3000 2000 300 4000也可以对多个元素赋同一个值,使用下面的格式:q)L:100 200 300 400q)L[1 3]:999q)L100 999 300 9995. 并列索引可以在list后仅仅使用空格符分隔来索引:q)L:100 200 300 400q)L[0]100q)L 0100q)L[2 1]300 200q)L 2 1300 200q)I:2 1q)L I300 200q)L ::100 200 300 4006. ? 查找返回右侧元素在左侧list中的位置索引q)1001 1002 1003?10021如果所查找的元素不在list里,那么将会返回整个list的count值,即长度:q)1001 1002 1003?10043find操作符右侧同样可以是一个listq)1001 1002 1003?1003 100110. 隐藏的索引1. 矩阵的隐藏索引 q)m:(1 2 3 4; 100 200 300 400; 1000 2000 3000 4000)q)m[1;]100 200 300 400m[;3]4 400 40002. 深度嵌套list的隐藏索引q)L:((1 2 3;4 5 6 7);(abcd;zyx;012);(“now”;“is”;“the”))q)L(1 2 3;4 5 6 7)(abcd;zyx;012)("now";"is";"the")q)L[;1;]4 5 6 7zyx"is"q)L[;;2]3 6cx2"w e"其中,L[;1;]表示取所有顶层元素在index 1的所有元素; L[;;2]表示取第二层元素在index 2的元素。11. 方阵list和矩阵1. 方阵方阵list是一个包含长度相等list的list,但这个方阵不一定是传统的矩阵,也可以是嵌套的矩阵,如下所示:q)L:(1 2 3; (10 20; 100 200; 1000 2000))q)L1 2 310 20 100 200 1000 2000可以使用flip函数对方阵进行转置操作,flip操作会分配新的储存空间并且拷贝原数据。q)L:(1 2 3; 10 20 30; 100 200 300)q)L1 2 310 20 30100 200 300q)flip L1 10 1002 20 2003 30 3002. 矩阵矩阵的正式定义是递归的,0维矩阵是一个标量,1维矩阵是一个简单list;对于n>1,n维矩阵是一个size相等的n-1维矩阵的list。可以通过list来索引一个矩阵:q)m:(1 2; 10 20; 100 200; 1000 2000)q)m 0 21 2100 20012. 一些有用的list操作符1. til以一个非负整数作为参数,返回从0开始的连续自然数q)til 100 1 2 3 4 5 6 7 8 9q)1+til 10q)2til 10q)1+2til 10q)-5+4*til 32. distinctq)distinct 1 2 3 2 3 4 6 4 3 5 61 2 3 4 6 53. where返回1b对应位置上的元素q)where 101010b0 2 4q)L:10 20 30 40 50q)L[where L>20]:42q)L10 20 42 42 424. group返回所有元素出现的位置q)group “i miss mississippi"i| 0 3 8 11 14 17 | 1 6m| 2 7s| 4 5 9 10 12 13p| 15 16End.