资讯专栏INFORMATION COLUMN

3. Q语言学习之路—Lists

wwq0327 / 2964人阅读

摘要:简单所有中的元素都是同种类型的,这种列表具有很好的储存和性能占据连续的储存空间。索引域如果索引在合理的边界之外,结果不是一个错误,而会返回一个值,表示,返回的值类型与第一个元素的类型一致。其结果是右侧元素占据左侧元素,除非右侧元素为值。

0. 概述

所有Q中的数据类型最终都是由list构造的:一个字段(dictionary)是由一对list构造的;一个表是一个特殊的字典;一个键表(keyed table)是一对表。因此熟悉一下list还是很重要的。

List支持索引取值,并且支持不同元素类型,可以把q list当作动态分配的数组。

1. 简介

1. 定义
一个list是一个存储q data的有序容器,使用括号表示,并且使用分号来分割元素。

</>复制代码

  1. q)(1; 1.1; `1)
  2. 1
  3. 1.1
  4. `1
  5. q)(1;2;3)
  6. 1 2 3
  7. q)("a";"b";"c";"d")
  8. "abcd"
  9. q)(`Life;`the;`Universe;`and;`Everything)
  10. `Life`the`Universe`and`Everything
  11. q)(-10.0; 3.1415e; 1b; `abc; "z")
  12. -10f
  13. 3.1415e
  14. 1b
  15. `abc
  16. "z"
  17. q)((1; 2; 3); (4; 5))
  18. 1 2 3
  19. 4 5
  20. q)((1; 2; 3); (`1; "2"; 3); 4.4)
  21. 1 2 3
  22. (`1;"2";3)
  23. 4.4

注意到没个的输出结果不太一样,第一个和最后三个是general list,意味着list中的元素非同质的。

list同样可以被复制给变量:

</>复制代码

  1. q)L1:(1;2;3)
  2. q)L2:("z";"a";"p";"h";"o";"d")
  3. q)L3:((1; 2; 3); (`1; "2"; 3); 4.4)

2. count
count相当于length, 返回list中元素的个数, 类型为long

</>复制代码

  1. q)count (1;2;3)
  2. 3

在q3中,list中元素最多有2^64-1个;在q2中,最多有20亿个。

count也可以对atom进行操作,尽管它们不是list,但仍返回1:

</>复制代码

  1. q) count 42
  2. 1

类似于count的操作符还有firstlast,返回list中第一个和最后一个元素。

2. 简单list

Simple list: 所有list中的元素都是同种类型的,这种列表具有很好的储存和性能(占据连续的储存空间)。

</>复制代码

  1. You can always use general list notation, even for simple lists.
    当q检测到一个list中元素是同种类型的时候,它会自动地将list转换为简单list

1. 简单整型list
对于任何数值类的List,在表示的时候,都可以忽略掉括号和分号,元素之间用空格隔开。

</>复制代码

  1. q)(100;200;300)
  2. 100 200 300
  3. q)100 200 300
  4. 100 200 300
  5. q)100 200 300~(100; 200 ; 300)
  6. 1b
  7. q)(1h; 2h; 3h)
  8. 1 2 3h

注意1 2 3h这种形式的表示,后缀h是作用在整个List的元素上,而(1;2;3h)中后缀h仅仅作用在最后一个元素上,该list是一个general list.

</>复制代码

  1. q)(1; 2; 3h)
  2. 1
  3. 2
  4. 3h

2. 简单浮点型list

</>复制代码

  1. q)123.4567 9876.543 99
  2. 123.4567 9876.543 99

q console压缩了小数部分为0的浮点数,上式中的99不是整型: 即当在一个float list中加入一个看似整型数字的时候,q会认为仅仅省略了数字右边的小数部分,因此你仍然得到的是一个简单浮点型list.

3. 简单Binary list
甚至可以省略空格符,
boolean类型以后缀b结尾:

</>复制代码

  1. q)(0b;1b;0b;1b;1b)
  2. 01011b
  3. q)01011b
  4. 01011b

byte类型以0x开头:

</>复制代码

  1. q)(0x20;0xa1;0xff)
  2. 0x20a1ff
  3. q)0x20a1ff~(0x20;0xa1;0xff)
  4. 1b

GUID类型与integer类型一样,以空格符分离

</>复制代码

  1. q)3?0Ng
  2. 8c6b8b64-6815-6084-0a3e-178401251b68 5ae7962d-49f2-404d-5aec-f7c8abbae288 5a5..

4. 简单Symbol list
中间没有空格分隔, 如果有空格会报错

</>复制代码

  1. q)(`Life;`the;`Universe;`and;`Everything)
  2. `Life`the`Universe`and`Everything
  3. q)`Life`the`Universe`and`Everything
  4. `Life`the`Universe`and`Everything
  5. q)`bad `news
  6. "bad

5. 简单char list和String

char list的简化形式像许多语言中的string类型;事实上, char list被称为string,由于string是list类型,因此不能比较两个不同长度string的大小。

</>复制代码

  1. q)("s"; "t"; "r"; "i"; "n"; "g")
  2. "string"
  3. q)"string"
  4. "string"

比较:

</>复制代码

  1. q)"string"="text"
  2. "length
  3. q)"string"~"text"
  4. 0b

6. 时间类型list
由于它们实际上是整型, 所以简化版本的simple list以空格符进行分隔:

</>复制代码

  1. q)(2000.01.01; 2001.01.01; 2002.01.01)
  2. 2000.01.01 2001.01.01 2002.01.01
  3. q)(00:00:00.000; 00:00:01.000; 00:00:02.000)
  4. 00:00:00.000 00:00:01.000 00:00:02.000

对于混合日期类型的list,所有元素的类型与第一个元素保持一致,可以追加一个类型指定符来指定list元素类型:

</>复制代码

  1. q)12:34 01:02:03
  2. 12:34:00 01:02:03
  3. q)01:02:03 12:34 11:59:59.999u
  4. 01:02 12:34 11:59
3. 空和单例list

1. 一般的空list
()( )表示一个空list,其在q console中没有显示。可以使用-3!()来强制显示()

2. 单例list
一个singleton表示一个只含有一个元素的list. 由于()除了用来生成列表外,还是数学表达式中的符号,单单使用(42)会得到元数据42,因此不可能用()来生成一个单例list.

单例list用函数enlist来创建:

</>复制代码

  1. q)enlist 42
  2. ,42

</>复制代码

  1. 只带有一个元素的string不能够被写为"a",这只是一个character的元数据,应当使用`enlist. This is a common error for qbies.

</>复制代码

  1. q)"a"
  2. "a"
  3. q)enlist "a"
  4. , "a"

注意单例并不一定要以atom作为它仅有的元素,它可以是任何q元素:

</>复制代码

  1. q)enlist 1 2 3
  2. 1 2 3
  3. q)enlist (10 20 30; `a`b`c)
  4. 10 20 30 a b c
4. 索引

1. 标识

[i]的形式:

</>复制代码

  1. q)(100; 200; 300)[0]
  2. 100
  3. q)100 200 300[0]
  4. 100
  5. q)L:100 200 300
  6. q)L[0]
  7. 100

2. 索引赋值

</>复制代码

  1. q)L:1 2 3
  2. q)L[1]:42
  3. q)L
  4. 1 42 3

注意向简单list赋值的时候,赋值类型必须与list元素的类型保持一致,否则会报错。

3. 索引域
如果索引在合理的边界之外,结果不是一个错误,而会返回一个Null值,表示“missing data”, 返回的Null值类型与第一个元素的类型一致。

</>复制代码

  1. q)L1:1 2 3 4
  2. q)L1[4]
  3. 0N
  4. q)L2:1.1 2.2 3.3
  5. q)L2[-1]
  6. 0n
  7. q)L3:(`1; 2; 3.3)
  8. q)L3[0W]
  9. `

4. 空索引和Null项

一个忽略的索引返回整个list:

</>复制代码

  1. q)L:10 20 30 40
  2. q)L[]
  3. 10 20 30 40

空索引与索引为空的list不同,后者会返回一个空的list,可以用指令-3!来强制显示

</>复制代码

  1. q)-3!L[()]
  2. "()"

双冒号::代表nil,即零(无)项,返list所有元素。

</>复制代码

  1. q)L[::]
  2. 10 20 30 40

同时,在list中使用::可以避免general list在被转换为simple list之后,无法再赋值的情况,具体见下例:

</>复制代码

  1. q)L:(::; 1 ; 2 ; 3; `a)
  2. q)L[4]:4
  3. q)L[4]:`a
5. 合并list

1. , join

逗号连接符,右边的list被拷贝到一个左边list的拷贝上,join同时支持atom,即支持作用于单元素。

</>复制代码

  1. q)1 2 3,4 5
  2. 1 2 3 4 5
  3. q)1,2 3 4
  4. 1 2 3 4
  5. q)1 2 3,4
  6. 1 2 3 4

可以使用(), x或者x, ()来生成x的单元素list,效果等同于enlist x

2. ^ merge
另一种合并list的方法是,对于两个长度相等的list, 可以使用^对它们合并。其结果是右侧元素占据左侧元素,除非右侧元素为null值。

</>复制代码

  1. q)L1:10 0N 30
  2. q)L2:100 200 0N
  3. q)L1^L2
  4. 100 200 30
6. list作为map

list将索引i映射到元素L[i]

</>复制代码

  1. I O
  2. 0 1 2
  3. 1 3 4
7. list 嵌套

1. 深度
list中的元素为list称为嵌套,嵌套的层数为深度depth, atom的depth是0, 简单list的depth为1.

</>复制代码

  1. q)L:(1;2;(100;200))
  2. q)count L
  3. 3

2. 图例

8. list 多重索引

可以使用L[1][2][0]或者L[1;2;0](注意是分号)来读取元素,前者被称为iterated indexing,后者被称为index at depth

其中,index at depth方法可以赋值,但是iterated indexing不支持赋值操作:

</>复制代码

  1. q)L:(1; (100; 200; (1000 2000 3000 4000)))
  2. q)L[1; 2; 0]: 999
  3. q)L
  4. (1; (100; 200; (999 2000 3000 4000)))
  5. q)L[1][2][0]:42
  6. "assign

构造matrix的一个方法:Reshape操作符#,下面代码中的0N(missing data)类似于python中的-1

</>复制代码

  1. q)2 0N#til 10
  2. 0 1 2 3 4
  3. 5 6 7 8 9
  4. q)0N 3#til 10
  5. 0 1 2
  6. 3 4 5
  7. 6 7 8
  8. ,9
9. 使用list索引

1. 提取多个元素
我们可以使用简单list作为索引, 索引可以是任意顺序,甚至可以是重复的。

</>复制代码

  1. q)L:100 200 300 400
  2. q)L[0 2]
  3. 100 300
  4. q)L[0 2 0]
  5. 100 300 100

2. 通过变量索引

</>复制代码

  1. q)L
  2. 100 200 300 400
  3. q)I:0 2
  4. q)L[I]
  5. 100 300

3. 通过嵌套list索引
返回的结果与嵌套索引list具有相同的shape

</>复制代码

  1. q)L:100 200 300 400
  2. q)L[(0 1; 2 3)]
  3. 100 200
  4. 300 400

4. 通过索引list赋值

</>复制代码

  1. q)L[1 2 3]:2000 3000 4000

赋值操作是按照从左到右的顺序进行的

</>复制代码

  1. q)L[3 2 1]:999 888 777
  2. is equivalent to,
  3. q)L[3]:999
  4. q)L[2]:888
  5. q)L[1]:777

因此,如果对重复项进行赋值的时候,最右边的项被保留下来。

</>复制代码

  1. q)L:100 200 300 400
  2. q)L[0 1 0 3]:1000 2000 3000 4000
  3. q)L
  4. 3000 2000 300 4000

也可以对多个元素赋同一个值,使用下面的格式:

</>复制代码

  1. q)L:100 200 300 400
  2. q)L[1 3]:999
  3. q)L
  4. 100 999 300 999

5. 并列索引
可以在list后仅仅使用空格符分隔来索引:

</>复制代码

  1. q)L:100 200 300 400
  2. q)L[0]
  3. 100
  4. q)L 0
  5. 100
  6. q)L[2 1]
  7. 300 200
  8. q)L 2 1
  9. 300 200
  10. q)I:2 1
  11. q)L I
  12. 300 200
  13. q)L ::
  14. 100 200 300 400

6. ? 查找
返回右侧元素在左侧list中的位置索引

</>复制代码

  1. q)1001 1002 1003?1002
  2. 1

如果所查找的元素不在list里,那么将会返回整个list的count值,即长度:

</>复制代码

  1. q)1001 1002 1003?1004
  2. 3

find操作符右侧同样可以是一个list

</>复制代码

  1. q)1001 1002 1003?1003 1001
10. 隐藏的索引

1. 矩阵的隐藏索引

</>复制代码

  1. q)m:(1 2 3 4; 100 200 300 400; 1000 2000 3000 4000)
  2. q)m[1;]
  3. 100 200 300 400
  4. m[;3]
  5. 4 400 4000

2. 深度嵌套list的隐藏索引

</>复制代码

  1. q)L:((1 2 3;4 5 6 7);(`a`b`c`d;`z`y`x`;`0`1`2);("now";"is";"the"))
  2. q)L
  3. (1 2 3;4 5 6 7)
  4. (`a`b`c`d;`z`y`x`;`0`1`2)
  5. ("now";"is";"the")
  6. q)L[;1;]
  7. 4 5 6 7
  8. `z`y`x`
  9. "is"
  10. q)L[;;2]
  11. 3 6
  12. `c`x`2
  13. "w e"

其中,L[;1;]表示取所有顶层元素在index 1的所有元素; L[;;2]表示取第二层元素在index 2的元素。

11. 方阵list和矩阵

1. 方阵

方阵list是一个包含长度相等list的list,但这个方阵不一定是传统的矩阵,也可以是嵌套的矩阵,如下所示:

</>复制代码

  1. q)L:(1 2 3; (10 20; 100 200; 1000 2000))
  2. q)L
  3. 1 2 3
  4. 10 20 100 200 1000 2000

可以使用flip函数对方阵进行转置操作,flip操作会分配新的储存空间并且拷贝原数据。

</>复制代码

  1. q)L:(1 2 3; 10 20 30; 100 200 300)
  2. q)L
  3. 1 2 3
  4. 10 20 30
  5. 100 200 300
  6. q)flip L
  7. 1 10 100
  8. 2 20 200
  9. 3 30 300

2. 矩阵
矩阵的正式定义是递归的,0维矩阵是一个标量,1维矩阵是一个简单list;对于n>1,n维矩阵是一个size相等的n-1维矩阵的list。

可以通过list来索引一个矩阵:

</>复制代码

  1. q)m:(1 2; 10 20; 100 200; 1000 2000)
  2. q)m 0 2
  3. 1 2
  4. 100 200
12. 一些有用的list操作符

1. til
以一个非负整数作为参数,返回从0开始的连续自然数

</>复制代码

  1. q)til 10
  2. 0 1 2 3 4 5 6 7 8 9
  3. q)1+til 10
  4. q)2*til 10
  5. q)1+2*til 10
  6. q)-5+4*til 3

2. distinct

</>复制代码

  1. q)distinct 1 2 3 2 3 4 6 4 3 5 6
  2. 1 2 3 4 6 5

3. where
返回1b对应位置上的元素

</>复制代码

  1. q)where 101010b
  2. 0 2 4

</>复制代码

  1. q)L:10 20 30 40 50
  2. q)L[where L>20]:42
  3. q)L
  4. 10 20 42 42 42

4. group
返回所有元素出现的位置

</>复制代码

  1. q)group "i miss mississippi"
  2. i| 0 3 8 11 14 17
  3. | 1 6
  4. m| 2 7
  5. s| 4 5 9 10 12 13
  6. p| 15 16

End.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/17954.html

相关文章

  • 8. Q语言学习之路—表

    摘要:其中代表了列的类型,表示了是否存在任何外键。事实上,语言会自动地识别满足表形式的列字典,在没有任何请求询问下,将其转换为表形式。结果显示的结果永远是一个表。被用来合并两个具有相同列的键表。属性表明对所有出现的值,相同的值都是互相邻近的。 0. 概述 表(Tables)和列表、字典一样,都是q语言中的第一类对象(First-class entity) Q表是*列导向的* Q表是从字典构...

    syoya 评论0 收藏0
  • [Leetcode] Merge Two Sorted Lists Merge K Sorted L

    摘要:注意因为堆中是链表节点,我们在初始化堆时还要新建一个的类。代码初始化大小为的堆拿出堆顶元素将堆顶元素的下一个加入堆中 Merge Two Sorted Lists 最新更新请见:https://yanjia.me/zh/2019/01/... Merge two sorted linked lists and return it as a new list. The new list...

    stefanieliang 评论0 收藏0

发表评论

0条评论

wwq0327

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<