Lua：列表
==========

本节我们来了解稍微复杂一点的数据类型—— `列表` （亦可称为数组）。

列表由一系列按特定顺序排列的元素组成。你可以创建包含字母表中所有字母、数字0~9或\
所有家庭成员姓名的列表；也可以将任何东西加入列表中，其中的元素之间可以没有任何关系。
鉴于列表通常包含多个元素，给列表指定一个表示复数的名称(如letters、digits或names)是\
个不错的主意。

在Lua中，用花括号( ``{}`` )来表示列表，并用逗号来分隔其中的元素。
下面是一个简单的列表示例，这个列表包含几名武将：

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   print(generals)

如果直接想用print把列表打印出来的话，Lua大概会打印出这种：

::

   table: 0x560c60b32e40

后面那一串数字每次运行都会有不同。鉴于这不是你要让用户看到的输出，下面来学习如何访问列表元素。

访问列表元素
-------------

列表是有序集合，因此要访问列表的任何元素，只需将该元素的位置或索引告诉Lua即可。
要访问列表元素，可指出列表的名称，再指出元素的索引，并将其放在方括号内。

例如,下面的代码从列表generals中提取第一名武将：

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   print(generals[1])  -- 打印出“徐盛”

在Lua中，第一个列表元素的索引为1，而不是0。这倒是很符合人的直觉，
不过对于已经了解过其他编程语言的人可能不是很友好，因为大多数编程语言列表下标都是从0开始。

依此类推，第二个列表元素的索引为2。根据这种简单的计数方式，要访问列表的任何元素，
都利用将其位置作为索引。例如下面的代码打印出generals列表的第2个和第4个：

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   print(generals[2])  -- 打印出“黄忠”
   print(generals[4])  -- 打印出“郭嘉”

你也可以新建一个变量来保存列表中取出的某个值：

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   local huangzhong = generals[2]
   print(huangzhong)  -- 打印出“黄忠”

修改、添加和删除元素
----------------------

你创建的大多数列表都将是动态的，这意味着列表创建后，将随着程序的运行增删元素。
例如，当一名角色阵亡时，就要从保存所有存活角色的那个列表删除掉他。

修改列表元素
~~~~~~~~~~~~~

修改列表元素的语法与访问列表元素的语法类似。要修改列表元素，可指定列表名和要修改\
的元素的索引，再指定该元素的新值。

还是用上面的例子：

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   generals[1] = "界徐盛"
   print(generals[1])  -- 因为generals的第一个元素已经被修改了，所以打印出“界徐盛”

就像修改变量的值那样，用一个等号也可以修改列表中对应那个索引的值。

往列表添加元素
~~~~~~~~~~~~~~~

在列表末尾添加元素
++++++++++++++++++

在列表中添加新元素时，最简单的方式是将元素附加到列表末尾。给列表附加元素时，
它将添加到列表末尾。继续使用前一个示例中的列表，在其末尾添加新元素"张飞":

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   table.insert(generals, "张飞")  -- [1]
   print(generals[3])  -- 甘宁
   print(generals[5])  -- 张飞

[1]处的代码使用了\ `函数`\ ``table.insert``\ 来将新元素“张飞”添加到了列表generals的末尾。

善用\ ``table.insert``\ 的话，我们可以轻易的动态创建一个列表。这意思是说，我们先创建一个空列表，
然后可以用 ``table.insert`` 向列表不断完善元素：

.. code:: lua

   local generals = {}
   table.insert(generals, "徐盛")
   table.insert(generals, "黄忠")
   table.insert(generals, "甘宁")
   table.insert(generals, "郭嘉")
   table.insert(generals, "张飞")
   print(generals[2]) -- 黄忠

这种创建列表的方式极其常见，因为经常要等程序运行后，你才知道程序会存储哪些数据，
比如要获得一个存储着“所有已受伤角色”的列表，就要从零开始创建，首先创建一个空列表，
然后扫描所有的角色，如果他受伤了，就把他添加到列表中。

在列表中间添加元素
++++++++++++++++++

使用函数 ``table.insert`` 还可在列表的任何位置添加新元素。为此，你需要指定新元素的索引和值。

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   table.insert(generals, 1, "张飞")  -- [1]
   print(generals[3])  -- 黄忠
   print(generals[5])  -- 郭嘉

注意[1]处的代码，他指明了新元素“张飞”应该插入到位置1上，于是Lua先把位置1以及\
后面的所有元素往右边挪一个位置，空出一个地方后再插入新元素，插入后的列表如下：

::

   { "张飞", "徐盛", "黄忠", "甘宁", "郭嘉" }

从列表中删除元素
~~~~~~~~~~~~~~~~~

在列表末尾删除元素
+++++++++++++++++++

和 ``table.insert`` 一样，使用 ``table.remove`` 即可删除列表的最后一个元素：

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   table.remove(generals)  -- [1]
   print(generals[4])  -- nil

[1]处的代码使用 ``table.remove`` ，删除了列表generals的最后一个元素，
所以我们再次试图用4去取的时候就会发现是 ``nil`` 了。

确定列表的长度
++++++++++++++

上面的代码中，就算我们删除了一个元素也无法很直观的看穿；如果能知道长度就好了，
删除一个元素长度就减少1，增加一个元素长度就加1，那不是很好吗？

在Lua中，我们使用井号（ ``#`` ）来获取列表的长度。用法很简单，在列表名字前面加个井号即可：

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   print(#generals) -- 4
   table.remove(generals)
   print(#generals) -- 3

删除任意位置的元素
+++++++++++++++++++

和 ``table.insert`` 类似， ``table.remove`` 亦可用于删除任何一个位置的元素，
只要你把要删除的位置告诉他就行了：

.. code:: lua

   local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
   table.remove(generals, 1)
   print(generals[2])   -- 甘宁

这里删除了列表的1号元素“徐盛”，产生了一个空位，Lua就会自动把后面的元素都左移一位来补齐了；
这也就是说，删除了“徐盛”后，列表就变成了 ``{ "黄忠", "甘宁", "郭嘉" }`` ，因此再访问2号元素就会得到甘宁。

.. note::

   Lua对于列表的操作基本就这些，新月杀为了易用性又添加了更多的操作办法。
   不过因为这里只是对Lua本身的功能进行讲解，所以我们到后面再来看更多更方便的办法吧。
