Lists列表
预览
复杂的数据是由简单的原子构成的,像前面我们列举出来的.理解一个list的意思是很重要的,几乎所有的q程序都包括处理lists.它的概念简单但是想快速建立是很复杂的.我们的步骤是在第一部分先介绍一个list的基本概念.选用一条快速的方法先看一下简单单一的list,然后我们再返回研究更具体的.
Lists介绍
一个list是一个有顺序的集合.一个list是一些顺序的原子集合和其他list组成的.我们先从最简单的例子开始学习,只包括原子类型的.
List定义和赋值
一个list将它们内容项装到圆括号里面并且用分号隔开.为了易读性,在下面最后一个例子中分号后面的空格是可选择性的
在前面的例子中,前面三个是简单的list,它们是由简单类型并且相同的类型组成.最后一个是一个综合的list,它包括的不是同一个类型的原始数据类型.这可能是原子类型的混合类型,单一类型嵌套list,或者是混合类型的嵌套list.
重要:list里面的项是有位置的(如,从左到右)这也是它定义的部分.lists(1;2)与lists(2;1)是不同的.SQL是建立在集上面的,它天生就无序.这种不同导致一些小的不同,这种不同表现在:在q查询出来的结果与SQL查询出来的结果集.q这种天生顺序list使得其处理时间序列很快速,但是这种在SQL中就表现得很差
Lists可以用变量赋值很像原子类型
数量
List中项的个数叫做count.可能用count命令(函数)来得到一个list的项个数.
这是我们函数的每个例子.
每一个原子类型的count都为1.
简单lists
一个简单的lists由相同类型的原子构成-符合数据概念里的向量.这种list在q中特别地处理,它们有单一的符号,占用存储空间少,比generallists计算也快.你可以为一个vector使用generallists,但是q无论什么时候将一个generallist转换为一个vector是可行的
简单的整型lists
下面的两个例子的是等价的(用空格代替了分号,省略了括号)
相似的符号用在短整和长整型的加了类型指示的简单lists
我们推断一个带类型指示在显示中是应用到整个list并不只是list的最后一项;否则,这个list不是简单的也不能以一般的形式显示出来.
简单的浮点型的lists
浮点型的简单list和real类型的在符号指示上类似,q控制台抑制了双精度型,当显示一个带有零值的双精度右边的浮点型的时候,但是值不是整型.
浮点型显示更有效率,浮点型的list没有双精度的部份(后面还有f)
简单二进制lists
简单的二进制的list包括数据值与类型指示.Thetypeindicatorforbooleantrailsthevalue.
Theindicatorforbyteleads,
注意:布尔原子类型的list需要相同的字节数存储.当简单符号issuggestive,多位没有压缩到单一字节.以上的list在5个字节存储空间保存了它的值.
简单symbollists
单一的原子的没有空格symbols的简单lists的简单符号
向原子中间插入一个空格将会导致一个错误
简单的charlists和字符串
简单的Charlist在大多数语言中看起来像string,由字符序列组成并且由双引号括起来.
注意:一个简单的charlist是一个string
输入简单lists
Lists能够用简单的符号来定义
最后,我们看一下一个混合了int和float的list转化为一个简单float的list
时间数据lists
从混合的数字类型中指定一个混合的时候型有一个不同的形式,在这个例子中,list取出第一项放入到list中,其它的项或加宽或放窄去匹配.
Toforce一个时间混合list,加一个类型指示符.
空的和单lists
只有一个项或者是没有项的listmerit特别的考虑
一般的空list
一个空的lists是非常有用的,两个括号,中间没有任何东西指示一个空的list
我们将会在creatingTypedEmpty一章,用一个特殊的类型可以定义一个空的list
只有单一项的list
在q中关于如何处理只含有一个单一项的list是quirk.叫做singleton.创建一个singleton表现了一个符号问题.第一一个包含singleatom跟individualatom是不同的..任意UPS驱动都会告诉你,box中的一个项跟unboxed的项是不一样的到目前为止,我们认识了如下的:
我们也认识了两个元素的lists.
如果创建一个只有单一项的list?好问题.答案没有这样的语法.你可能会认为将一个项放到括号中就可以了,但根本不起作用,结果是一个atom.
Q中括号的作用就是多处理.双括号是用来划分特定的list.双括号也用作表达式组-thatis,在圆括号内隔离表达式的结果.Thelatterusageforces(42)tobethesameastheatom42andsoprecludestheintentioninthespecificationofsingletonabove.
用单一项去构建一个list使用enlist函数,会返回一个它右边的singletonlist
区别一个atom和一个相等的singleton,检查类型符号.
在继续学习之前最后一次检查,确定你明白下面的也是用singleitem定义一个list
Indexing
回忆一下一个list根据item的位置从左到右排序.从list的最开始的位置开始的偏移就index.因此第一个项index为0,第二个index为1,等.一个有长度为n的list那么index取值范围就是0->n-1
Index符号
有一个listL,通过索引取值例子如下:
Indexed赋值
list也可以通过索引赋值.
重要:index给一个简单list赋值时会强制地进行类型匹配检查并且没有类型提升.当你给你一个list重新赋值的时候,类型必须严格匹配,一个窄的类型不能被加宽.
Thismaycomeasasurpriseifyouareaccustomedtonumericvaluesalwaysbeingpromotedtowidertypesinaverboselanguage.
IndexingDomain
如果索引给的类型不对那么将导致一个错误
如果你尝试索引一个越界的值,出现的不是一个错误,而是一个null值.如果简单list,那个这个null是atoms类型,如果是generallists,结果将是0n.
一种方法知道访问一个不存在的index的时候将是"missingvalue".这样,索引list的一个位置到最后一个位置是非常容易的,especiallyifyou'renotusedtoindexingrelativeto0.
空索引和Null项
一个空的索引返回整个list
注意:一个空的索引不是索引一个空list,后者返回一个空list
用双冒号组成的指示一个空项,它允许外在的符号或者是programmatic一个空index的产生
高级:null类型项是没有定义的,特殊情况下,它的类型在list中是不匹配任何类型的.
Asaconsequence,inclusionofthenulliteminalistforcesthelisttobegeneral.
Thiscanbeusedtoavoidanastysurprisewhenqistooclever.Toseehow,considerthegenerallist,
现在,看一下给list的最后一项重新赋值会发生什么.
这个list被转成一个简单的int型的list!再尝试改回原来的值导致错误
这样可以将null项放到list,强迫其保持general
变量lists
List可以由变量创建
List合并
对于list也许普遍的操作就是将两个list合并起来,合并操作符(,)将一个的右边加到一个的左边尾部然后返回一个结果.它两边可以接收atom的参数
如果参数不是同一类型,结果将会是一个generallist.
注意:Toaccepteitherascalaroralistxandproduceauniformshape,usetheidiom,
whichalwaysyieldsalistwiththecontentofx.
ListsasMaps
目前为止我们看到了list的静态集合.我们可以将list当作map,前提是提供索引.一个listL意思是单Map非负整数0,.....,n-1.list映射将输出值L[i]赋给输入值i.Succinctly,theI/Oassociationforthelistis,
下面是一些简单的lists的I/O表
101102103104
(`a;123.45;1b)
(12;34)
头两个例子示例了atoms集合的范围.最后一个例子有一个lists组成的范围.
一个list不仅看起来像map,它是一个map符号是一个I/O表赋值的shortcut.这是一种看待事情非常重要的方式.我们将会在PrimitiveOperations看到一个嵌套的list被看作是一个multivalentmap范围是atoms.
Fromtheperspectiveoflistasmap,thefactthatindexingoutsidetheboundsofalistreturnsnullmeansthemapisimplicitlyextendedtothedomainofallintegerswithnullvaluesoutsidethelistitems.
Nesting
Datacomplexityisbuiltbyusinglistsasitemsoflists.
深入(Depth)
现在我们学习了简单lists,现在返回到generallists.我们可以用list嵌套list.嵌套的级数就做Depth.Atoms是有0深度,简单list有1深度.
复杂list的符号影响它们的嵌套.为了教育目的,在这个部分,我们将经常使用general符号去定义简单lists;然而,控制台经常显示简单的格式.在后来的部分,我们将仅使用带简单符号的简单list.
下面是一个有两级深度并且三项的list,前两项是atoms最后一项是一个list.
下面是一个内部list的简单符号
图表示
我们用图来帮助理解.一个atom表示为一个圆并且带着值.一个list表示为一个方格带着它的项.一个generallist表示为一个方格包含方格和atoms.
例子
下面是一个有两级深度并且有两个项的list,每一项又是一个简单list
下面是一个有两级深度并且有三个项的list,每个项又是一个generallist
下面是一个有两级深度并且有一个简单list的项的list
下面是一个有三级深度并且有两个项的list,每二项是一个有两级深度并且有三项的list,最后一项是一个有四项的简单list.
下面是一个矩形的list,它可能想像为是一个3X4的矩阵(请试想二维数组概念)
深度的索引
我们可以直接索引到嵌套list的每个项
重复项的索引
通过索引去得到list的项往往得到是一个嵌套list的最高项
回忆q解析表达式是从右到左的,我们解释第二个retrievalaboveas,,
得到L的索引1的项,Alternatively,readingitfunctionallyasleft-of-right,
得到L的第1位置的项
L[1]的结果是它自己,我们可以用一个单一索引得到它的项
读作:
从L中得到第一个索引项的第二个索引位置个的项
从L中得到第一个索引项,然后从中得到第二个索引项
我们可以重复单一索引多一次去从一个内部嵌套的list中得到项
读作,
得到第一个索引位置上的第二个索引项的第0个项的值
或者是得到L的第一个索引项,然后从中得到第二个索引项,最后再从其中得到第0个项
深度索引的符号
对于上面的表式方法还有一种写法
用这种方法得到嵌套list里的内部项就叫做indexingatdepth.
重要:深度索引时的分号是必须的
在深度也可以通过索引赋值.
为了验证深度符号索引是合理的,我们返回到矩阵的例子
深度符号索引建议将m看作是多面的矩阵,而重复单一索引建议将m看作是数组的数组.
List索引
Alistofpositionscanbeusedtoindexalist.
得到多项
在这个部分,我们可以看到q在处理多lists的强大.
我们知道如何索引单个项
扩展一下,我们也可以通过多索引得到多项
索引可以以任何顺序出现,得到相应的项
也可以出现重复的索引
更多的例子
这解释了包含了分号操作符在深度索引是精华.Leavingthemouteffectivelyspecifiesmultipleindices,andyouwillgetacorrespondinglistofvaluesfromthetoplevelasaresult.
通过简单list索引
通过generallist索引
观察一个每一个例子,通过简单list得到的结果是一个新的list,它的值得到的是list的第一层,它的形状看起来像索引list.特殊情况下,得到的list跟索引list是一样的.这里建议索引的行为是一个non-simple-list.
这里指出通过non-simplelist索引得到的结果,得到的结往往跟索引的形状一样.
高级:Moreprecisely,theresultofindexingviaalistconformstotheindexlist.Thenotionofconformabilityoflistsisdefinedrecursively.Allatomsconform.如果两个list有相同数目的项并且相关联的项相似的,那么说这两个list相似(conform).简单地说,两个list形状一样就是相似.
通过list索引赋值
回忆一个通过项索引赋值
延伸到通过简单list赋值
注意:通过简单list赋值是根据索引顺序来处理的,例如,从左到右,因此
等价于
如果在索引里有重复的项索引,那么后面的将会覆盖前面的.
你可以通过一个索引对list的几项更赋值
Juxtaposition
现在我们熟悉了通过索引得到值和赋值,我们介绍一个简单的形式.它允许省略括号和juxtapose索引数之间用空格隔开.下面一些例子:
你选择哪些是个人的喜爱问题.在这个手册中我们通常使用括号,因为这种在其它语言中多见.有经验的q程序员通常使用juxtaposition降低表达式密度.
Find(?)=
双值的查找(?)返回索引
Performingfindonalististheinversetopositionalindexingbecauseitmapsanitemtoitsposition.
如果你试图在一个list中查找一个不存在的项,那么会返回一个跟它长度相等的值
你可以这么看这个问题,你要查找的项不在list,它是在list最后一项的后面,你可以加这一项到list里.当然,扩展一下查找
ElidedIndices
ElidingIndicesforaMatrixList
我们返回到深度索引嵌套list的情形.简单地,看一下下面这个看起来像矩阵的list
类似的一般的矩阵,我们也可以通过提供部分索引而得到行或是列
观察省略最后索引降低toitemindexingatthetoplevel.
注意:在前面的例子中,两种格式有相同的结果,但是第一种更能表达意思
省略其他比省略第一个索引更有意思读m[;3]的方法见上面,
从list所有的项最顶开始读每三个项.
ElidingIndicesforaGeneralList
看看其它的嵌套
解释一下L[;1;],
得到list从顶开始所有的项的第二项值
解释一下L[;;2],
得到list从第二层开始的每个list的第三项值
观察L[;;2]试图得到第三项string导致null值"";所有空格在结果中.
推荐:通常来说,如果你在elidingindices的时候不省略尾部的分号会更清晰.例子
在这部分的检测中,我们用简单数组联合一个elided索引.然后我们可以得到cross-section通过用elided联合和list索引.
解释如下
从位置0和1,从所有行0和2的列中得到项
RectangularListsandMatrices
RectangularLists
在这个部分,我们深度研究一下前面提到的像矩阵的list.一个rectangular是一个嵌套list的list,都有相同count.这并不意味着rectangularlist就一定是矩阵,它也可以是另外的嵌套方式.例如,接下来的是一个rectangular因为每一个项count都是3,但它不是一个矩阵.
在rectangularlist中,elisionofthesecondindexcorrespondstogeneralizedrowretrievalandelisionofthefirstindexcorrespondstogeneralizedcolumnretrieval.
高级:一个rectangularlist能够用flip调换(flip会在以后章节学到),意味着行和列都受影响,在深度索引中很有效率地反向头两个索引,例如,
Matrices
Matrices