# table 函数库使用指南

请参考：[数据类型 - table](../../../language-reference/datatype/table/_.md)
 
## 一. 在数组中插入删除元素 

1. table.insert 函数 <a id="insert" href="#insert">&#x23;</a>


    函数原型：

    `table.insert(tab,value ,pos = 1)  `

    说明：

    在 table 类型参数 tab 中插入元素(value)。

    参数 pos 指定插入位置.如果指定 pos 参数,table.insert首先在`tab[pos]`插入 value 并将后面的所有元素顺序向后移动。pos 为可选参数，默认值为1( 在数组开始插入 )。

2. table.remove 函数 <a id="remove" href="#remove">&#x23;</a>


    函数原型：

    `value = table.remove (tab ,pos = 1)  `

    说明：

    在数组指定位置移除元素，然后从此位置开始将所有元素前移一位。  
    可选用 pos 参数指定移除元素的位置，默认值为1(即在数组开始移除）。

    返回值为移除的元素。

    如果您不希望在删除元素后改变其他的元素的位置，可以使用赋值为 null 的方法删除一个元素。

    示例：
    
    ```aardio
    var tab = {"a";"b";"c";"d";"e"}

    //移除第二个元素,后面的元素全部向前移动一个单位.
    table.remove (tab ,2); 

    //删除第二个元素,不会改变其他元素的位置
    tab[2] = null; 。
    ```

  
## 二. 用数组实现堆栈操作 

  
堆栈操作避免了数组的重新排序，效率高于 table.insert,table.remove 。  

1. table.push 函数 <a id="push" href="#push">&#x23;</a>


    函数原型：
    
    `table.push(tab ,value[, value , ... ] ) ` 
    
    函数说明：

    在数组尾部添加一个或多个值。table.push返回新数组的长度（最后一个元素所在的索引)  

    如果连续 push 多个值，例如：  

    ```aardio
    table.push(tab ,a)  
    table.push(tab ,b)  
    table.push(tab ,c)  
    ```
    
    应当放到一个push操作中效率会更好一些，例如：

    ```aardio
    table.push(tab,a,b,c)  
    ```

2. table.pop 函数 <a id="pop" href="#pop">&#x23;</a>

  
    函数原型：

    `table.pop(tab [, n] )  `
    
    函数说明：

    在数组尾部弹出一个或n个值。 n为可选参数，默认为 1 。
    返回值为一个或 n 个移除的数组元素。  

3. 示例

    ```aardio
    //实现一个堆栈类
    class stack { 
        //继承 stack 命名空间的静态成员
        @{ _get = self }

    }
    namespace stack{
        push = function( ... ){
            ..table.push( owner , ... ); 
        }
        pop = function( n ){
            return ..table.pop( owner , n ); 
        }		
    }


    //创建新的堆栈对象
    var sk = stack();

    //压入一个或多个参数
    sk.push("a","b","c") 

    //弹出一个或多个值
    var a,b,c = sk.pop(3);
    ```  

> 注意：如果参数尾部调用了返回多个值的函数则会增加多个参数，例如 `table.push( tab,tonumber("123") )` 里面的 `tonumber("123")` 会添加 `123,3` 这两个参数。如果只希望添加第一个返回值，可将函数调用放到一对圆括号内以转换为单值表达式，例如 `table.push( tab,( tonumber("123") ) )` 。

## 三. table.range 函数 <a id="range" href="#range">&#x23;</a>

### 1. 获取稀疏数组的索引范围

函数原型：

`var min , max = table.range( array )`

函数说明：

获取 table 类型参数 array 的数组索引最小值与最大值。

虽然这个函数也可以用于有序数组，但一般只有稀疏数组才需要用到  table.range 函数。

普通有序数组，数组索引默认从 1 开始，[使用 # 操作符可以直接获取数组长度](../../../language-reference/datatype/table/_.md#array)。

示例：

```aardio
import console; 

//创建数组，数字索引默认从1开始
var arr = { 123;456;77;99 };
 
console.log( table.range( arr ) );
console.pause();
``` 

### 2. 生成指定数值范围的有序数组

也可以在调用 table.range 函数指定一个数值范围作为参数，用于生成序列数组。

函数原型：

`var array = table.range( start,stop,step[,map] )`  
`var array = table.range( start,stop[,map] )`  
`var array = table.range( stop[,map] )`  

指定数值范围时，table.range 返回一个序列数组，包含的数值从 start 指定的数值开始到 stop 指定的数值结束（返回数组包含 stop），数值递增步长由 step 指定。省略 step 则步长默认为 1。如果不指定 start 则默认从 1 开始。

参数尾部可选用 map 参数指定一个回调函数，该函数接收当前数值并返回新的数组值。

## 四. 遍历数组   
  
用 for 循环顺序遍历有序数组所有元素。

参考：[for 循环语句](../../../language-reference/statements/looping.md#numeric-for)
  
```aardio
import console; 

//创建数组，数字索引默认从1开始 
var tab = {123;456;789};

//循环遍历数组
for i=1; #tab;1 {
	console.log( tab[i] );
}

console.pause();
```  

上面的方法对于稀疏数组是低效的。

例如：

```aardio
var tab = {};
tab[100000] = 100; 
```  

这时候，我们可以用泛型 for 循环遍历稀疏数组元素。

[泛型 for 与迭代器](../../../language-reference/statements/iterator.md)
  
```aardio
import console; 

//创建数组 
var tab = {"字符串";123;"字符串2";23;56;78;99;123;0;test=123}; 

//稀疏数组
tab[1000] = 123; 

//遍历数组
for index,value in tab {
	//仅遍历索引为数值的成员
	if( type(index) == "number" ){
		console.log( index , value )
	}
}

console.pause();
```  

## 五. 数组排序 <a id="sort" href="#sort">&#x23;</a>


函数原型：

`table.sort (tab [, compareProc])`
 

说明：
  
对数组参数 tab 重新排序，直接修改原数组，函数无返回值。

cmpProc 可选指定一个排序回调函数用于比较两个元素的大小。  
table.sort 在排序过程中，每遇到两个元素就调用 compareProc 函数比较大小,并将两个元素作为参数传递给 compareProc 函数。  

```aardio
compareProc = function(next) {
    return owner  < next; 
};
```
要特别注意 compareProc 里用 owner 表示左操作数。owner 是自动传递的参数，不需要在形参列表中指定。

compareProc 返回 true 表示 owner 应排序在前，否则返回 false。注意函数判断的是小于或大于而不是小于等于或大于等于，两值相等不应当返回 true。 如果没有提供排序回调函数，table.sort 默认调用小于操作符比较两个元素的大小。

请看下面的例子：

  
```aardio
import console;

//定义数组
var array ={3;4;7;8;6;5;2;1}

//默认排序
table.sort(array);

//显示 1 2 3 4 5 6 7 8 
console.dumpTable(array)

//自定义排序函数以比较元素大小
var compareProc = function(next)  {
	//反过来排序，owner 较大时排序在前（返回 true）
    return owner  > next ;
};

//自定义排序
table.sort(array,compareProc);

//显示倒序
console.dumpTable(array)

console.pause();
```  

table.sort 是对数组的值域进行排序，不能对字典排序，也不能对键域(下标域)进行排序。如果我们需要对字典进行排序，可以自已写一个迭代器。将字典中的数据复制到一个数组中然后进行排序。

实际上标准库有个 table.eachName 函数可以实现此功能。

下面我们介绍如何使用 table.eachName 迭代器对  table 中名值域进行排序. table.eachName 的源码在 builtin.table 库中可以找到。

示例：
  
```aardio
//定义表
var tab ={c=2;d=7;e=4;g=2;h=8;a=1;b=6;f=5;i=1;j=1;k=9};
 
//按键名排序遍历表
for k,v in table.eachName(tab) {
	print(k,v);
}
```  

## 六. 反序  <a id="reverse" href="#reverse">&#x23;</a>


函数原型：
  
`table.reverse(array)  `

函数说明：
  
将一个数组按原来的顺序反向排列。  
注意这个函数没有返回值，直接修改原来的数组。

函数示例：
  
```aardio
var array = { 1;2;3;4;5;6;7}
table.reverse(array); //反序排列 

for(i = 1;#tab;1){
    print( array[i] ) 
}
```  

## 七. 展开数组 <a id="unpack" href="#unpack">&#x23;</a>


函数原型：

`table.unpack(array,b=1,e=#tab)`

函数说明：

参数 @array：表对象  
参数 @b：起始索引，默认为 1  
参数 @e：结束索引，默认数组长度。  
返回值：从索引位置 b ，到索引位置 e ，索引位置可为负数(表示自数组尾部倒序索引)，拆分并返回 table 对象的数组成员。  
  
如果不指定结束索引，或任何一个索引参数为负数时，table.unpack() 将会获取有序数组长度，这种用法不支持稀疏数组。

参考：[稀疏数组](../../../language-reference/datatype/table/_.md#sparse-array)

当起始索引与结束索引都明确指定且都大于零，table.unpack() 则不检测顺序数组的长度，因此可以支持稀疏数组，例如下面的代码:

```aardio
table.unpack( {1;2;[7]=7},1,7 )  //返回1,2,null,null,null,null,7
```  

改用 table.unpackArgs 可自动获取稀疏数组的索引范围并展开所有元素。table.unpackArgs 最好不要用于有超大索引的稀疏数组，这个函数一个常见的作用是用来展开被包装到数组中的不定参数，参数组成的数组可能因为包含 null 值而成为稀疏数组，但包含的元素一般都很少，不会有超大索引，所以适合用  table.unpackArgs 展开 。

## 七. 首尾截取数组 

1. table.left

    原型：

    `table.left(array,len)`

    说明：

    参数 @array：数组（表对象）
    参数 @len：从数组左侧返回的数组元素个数。  
    返回值：从数组左侧拆分并返回数组的 len 个数组成员。len 如果为负数，则从右侧倒数指定索引的成员向左截取所有元素。

2. table.right

    原型：

    `table.right(array,len)`

    说明：

    参数 @array：数组（表对象）
    参数 @len：从数组右侧返回的数组元素个数。  
    返回值：从数组右侧拆分并返回数组的 len 个数组成员。len 如果为负数，则从左侧倒数指定索引的成员向右截取所有元素。

## 八. 序列化 table

函数原型：

`table.tostring( tab [,binary])`

函数说明：

将第一个参数 @tab 指定的 table 对象序列化为 aardio 代码构造表的字符串，可序列化的元素必须使用合法的标志符、或数值作为键。

如果指定第二个可选参数 @binary 为 true，则序列化使用二进制指令，序列化得到的表不适合直接编辑。

函数示例：

```aardio
import console; 

var tab = {1;2;3;a=123;b='456'};
str = table.tostring( tab ); //序列化为字符串（aardio代码）
console.log( table.tostring( tab ) );

console.pause();
```  

## 九. 拼接 table 

函数原型：

`table.concat(tab,tab2[,tab3 [,... ] ])`

函数说明：

将多个表连接为一个新的表，表中如包含数组，索引值修改为原索引值加上在新表中的位置  

函数说明：
  
```aardio
import console;

var tab = {1,2,3};
var tab2 = {4,5,6};

//将多个表拼接为一个表
var tab3 = table.concat(tab,tab2 ); 
console.log( table.unpack( tab3 )  );

console.pause();
```