AutoHotKey伪数组、数组与关联数组

数组.jpg

前边我们讲了变量,打了一个形象的比喻,就是把变量比作吃饭的碗,量(值)就是饭。其实呢,数组跟变量是有直接关系的,变量是数组的基础,变量的是碗的话,数组就好像是一个多功能的饭盒,可以同时装好多种饭菜,神奇吧!!

来吧!然我们一起领略一下数组的神奇。常见的数组有三种,伪数组、数组、关联数组。

伪数组

伪数组应该是AutoHotkey中特有的概念,每个伪数组实际上只是一系列连续编号的变量或函数的集合,它们的每一个被视为伪数组的“元素”。AutoHotkey 内部不会以任何方式把这些元素链接在一起。任何接受 OutputVar 或能赋值的命令都可以用来创建伪数组。
最简单的例子是使用赋值运算符(:=),如下所示:
Array%j% := A_LoopField
通过在索引间使用自选分隔符可以创建多维伪数组,例如:
Array%j%_%k% := A_LoopReadLine

操作伪数组下面的例子演示了如何创建和访问伪数组,这里是从文本文件获取一系列的名称:

; 例1:写入数据到伪数组:
ArrayCount := 0
Loop, Read, C:\Test.txt   ; 循环获取文件中的每行,一次一行。
{
    ArrayCount += 1  ; 记录伪数组中的项目数,这里不记录后面获取不方便。
    Array%ArrayCount% := A_LoopReadLine  ; 把此行保存到伪数组中的下一个元素。
}

; 例2:从伪数组中读取:
Loop, %ArrayCount%
{
    ; 下一行使用 := 运算符获取伪数组元素:
    element := Array%A_Index%  ; A_Index 是内置变量。
    MsgBox, % "索引号" . A_Index . "的元素的值为" . Array%A_Index%
}

看过这两个例子后,里面的操作中我们只是连续的操作变量罢了,与操作普通变量在性质上没有区别。唯一的区别是名称,这系列变量的名称一般后面部分为数字,比较典型的如 StringSplit、WinGet ListRegExMatch 这些命令创建的伪数组。还有些命令虽然会创建一系列变量,变量的名称却不是以数字结尾,如 GuiControlGet Pos、SysGet 等。

数组

简单数组创建数组:

Array := [Item1, Item2, ..., ItemN]
Array := Array(Item1, Item2, ..., ItemN)

获取项:

Value := Array[Index]

对项进行赋值:

Array[Index] := Value

插入一个或多个东东到给定序号位置:

Array.InsertAt(Index, Value, Value2, ...)

追加一个或多个东东:

Array.Push(Value, Value2, ...)

移除项:

RemovedValue := Array.RemoveAt(Index)

移除最后一项:

RemovedValue := Array.Pop()

如果数组不是空的, 那么 MinIndexMaxIndex/Length 分别返回数组中当前使用的最小和最大的索引. 由于最小的索引几乎总是 1, 所以 MaxIndex 经常返回项目数. 如果没有整数键, MaxIndex 返回空而 Length 返回 0 ,对数组内容进行依次循环可以通过索引或 For 循环实现。
例如:

array := ["one", "two", "three"]

; 从 1 到项目数进行重复:
Loop % array.Length()
    MsgBox % array[A_Index]

; 枚举数组内容:
For index, value in array
    MsgBox % "Item " index " is '" value "'"

关联数组

关联数组是一种数据结构,本质上是一种特殊的对象。操作关联数组自包含关联数组可以使用以下两种创建
<pre>Array := {KeyA: ValueA, KeyB: ValueB, ..., KeyZ: ValueZ}
Array := Object("KeyA", ValueA, "KeyB", ValueB, ..., "KeyZ", ValueZ)</pre>

例如:

; 创建数组后,初始为空:
Array := Object()

; 写入数据到数组:
Loop, Read, C:\Guest List.txt ; 依次获取文件中的每行文本。
{
    Array.Insert(A_LoopReadLine) ; 添加到数组中。
}

; 从数组中读取数据,在一般情况下建议使用这种方式(即 for 循环):
for index, element in Array
{
    MsgBox, % "索引号为" . index . "的元素的值为" . element
}

这个例子仅演示了对象提供的功能中很小的一部分,还可以可以设置、获取、插入、移除和枚举项目。除了数字,还可以把字符串和对象作为键使用。对象可以作为值存储到其他对象中并且可以作为函数参数或返回值传递。对象还可以用新功能进行扩展。

For 循环与 Loop 循环

对于这样特殊的关联数组,还可以把上面的 For 循环替换为 Loop 循环:
; 使用传统方式

Loop, % Array.MaxIndex()
{
    ; 使用“Loop”,索引必须是连续的数字,从 1 到数组中元素的个数(或者必须在循环中进行计算)。
    MsgBox, % "索引号为" . A_Index . "的元素的值为" . Array[A_Index]
}

实际上不建议使用 Loop 对关联数组进行循环操作(很蹩脚),上面的例子中数组的索引从 1 开始且是连续的整数,所以可以使用 Loop 循环。然而,关联数组中的键可以为字符串、整数或对象,即使键为整数时还可能是稀疏分布的,例如{1:"a",1000:"b"},在这些一般情况下都无法使用 Loop 代替。

数组、伪数组与关联数组的之间的比较和应用

尽管 Insert() 和枚举数有它们的用途, 不过一些用户可能会发现使用它们比用更传统的方式容易些。下面的例子中把伪数组和关联数组的操作方式进行比较,其中注释中的为伪数组的操作方式:

; 与变量可直接使用不同,数组在使用前必须初始化:
Array := Object()

; Array%j% := A_LoopField
Array[j] := A_LoopField

; Array%j%_%k% := A_LoopReadLine
Array[j, k] := A_LoopReadLine

ArrayCount := 0
Loop, Read, C:\Guest List.txt
{
    ArrayCount += 1
    ; Array%ArrayCount% := A_LoopReadLine
    Array[ArrayCount] := A_LoopReadLine
}

Loop, %ArrayCount%
{
    ; element := Array%A_Index%
    element := Array[A_Index]
    ; MsgBox % "Element number " . A_Index . " is " . Array%A_Index%
    MsgBox, % "Element number " . A_Index . " is " . Array[A_Index]
}

这个是帮助中的例子,但实际意义不大,因为它是以伪数组的方式在伪数组的功能上进行的比较。例如使用 ArrayCount 变量保存数组元素个数,我们知道这对于关联数组是多余的,它的元素个数是由程序维护,可以直接使用 MaxIndex() 方法获取,而且获取值时无需通过元素个数,可直接 for 循环。帮助中提到这个比较会“让大家更容易从原来使用伪数组的习惯中过渡过来”,不过我个人认为这样做是否像用汉字标出英语单词的发音来学英语呢?
关联数组使用与简单数组非常相似的语法. 事实上, 在 v1.x 中它们是相同的东西. 然而, 把 [] 视为简单线性数组有助于保持其作用清晰, 并且改善您脚本与 AutoHotkey 未来版本的兼容性, 未来版本中可能改变实现方式.

小结

目前而言,在支持创建伪数组的命令中还是需要伪数组(伪数组存在的必要性),在其他地方关联数组具有优势(关联数组的功能强大、使用方便),即关联数组尚无法完全取代伪数组(即使作为中间产物),尽管我推荐在一般情况下使用关联数组。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容

  • 作者:amnesiac 首发:官方论坛之中文版 伪数组应该是 AutoHotkey 中特有的概念,下面的内容需要稍...
    amnesiac阅读 586评论 0 1
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,292评论 18 399
  • 第一部分 打好基础 Laying the Foundation 第一章 欢迎进入软件构建的世界 Welcome t...
    白桦叶阅读 4,519评论 0 17
  • 楊孜 你我相距 何止千里 但妳的东边日出 却让我西边下雨 妳霸占分分秒秒 临幸着几世修为 我的花花草草 锦绣文章 ...
    楊孜阅读 286评论 0 0
  • 三月,情未央,花开,倾城。 沿着三月的时光,我翻阅着曾经,那一份初相遇,晚春,初夏,那些浓浓的情怀,也便兀...
    一指流沙1阅读 199评论 2 2