Ninox 中的数组
简单数组
操作文本或数字数组非常直接:
var myArray := ["a", "b", "d"];
index(myArray, "b");
myArray := array(myArray, ["c"]);
myArray order this;
对文本或数字数组,也可以使用 order、sort 和 unsort 进行排序。
更多与数组相关的函数,请参阅 Ninox 文档。
二维数组
Ninox 不直接支持二维数组。作为替代,可以使用由 JSON 对象组成的数组。
例如,按 d2 字段的第二个元素对数组排序:
var myArray := [{'d2':["a", "Z"]}, {'d2':["b", "B"]}, {'d2':["c", "C"]}, {'d2':["d", "D"]}];
(myArray order by item('d2', 1));
这段代码返回:[{"d2":["b","B"]},{"d2":["c","C"]},{"d2":["d","D"]},{"d2":["a","Z"]}]
筛选数组
您可以像筛选 select 的结果那样筛选数组。对于文本或数字数组,用 this 指代正在被筛选的值:
var myArray := ["Jan", "Fred", "Jacques"];
myArray[this like "J"] order this;
对于 JSON 数组,则直接使用键名:
var myArray := [
{ 'prénom' : "Jan", nom : "Augustin" },
{ 'prénom' : "Fred", nom : "Baillot" },
{ 'prénom' : "Jacques", nom : "Tur" }
];
myArray[nom like "i"] order 'prénom';
这段代码返回一个 JSON 数组:[{"prénom":"Fred","nom":"Baillot"}, {"prénom":"Jan","nom":"Augustin"}]
对 JSON 数组执行自定义操作
对于 JSON 数组,您可以加入一个代码块(放在圆括号中),为每一次迭代执行自定义操作。与 for in 一样,结果数组的类型取决于代码块中最后一行代码。
示例:计算全名(prénom + nom)的长度:
var myArray := [
{ 'prénom' : "Leo", nom : "Martin" },
{ 'prénom' : "Paul", nom : "Garnet" },
{ 'prénom' : "Pierre", nom : "Dur" }
];
var nameLengths := myArray[nom like "a"].(
var fullName := ---{'prénom'} {nom}---;
length(fullName)
);
nameLengths;
这段代码返回一个数字数组 [10, 11],表示这些全名的长度。
初始化一个带类型的空数组
在 Ninox 中,创建仍然带有正确记录类型的空数组的惯用技巧,是执行一个带 where false 过滤条件的 select。
该查询返回零条记录,但保留了数组元素的类型。
"Empty Invoice Item array:";
let t := (select 'Invoice Item' where false);
- 现在
t是一个数组,其元素为 Invoice Item 类型。 - 因为它虽为空却带有类型,可以放心地用作
array()操作的起点。
为什么不直接用 []?
字面量 [] 是一个无类型数组。它通常能用,但当与记录集合上的 array() 结合使用时,Ninox 可能会报告类型不一致。
select … where false 这种写法可以彻底避开这个问题。
为基本类型(数字、文本、JSON……)创建空数组
当您需要一个存放标量值(数字、文本字符串或 JSON 对象)的空数组时,并没有可供 select 的底层表。
不过您仍然可以先用一个占位元素初始化 [],再立刻把它过滤掉,从而得到一个带类型的空数组:
"Empty number / text / JSON array:";
let t := [1][false]; "t is now an empty but number typed array";
[1] 生成一个单元素的数字数组;[false] 过滤器移除该元素,留下一个仍保有数字类型的空数组。
如果需要文本或 JSON 类型,就把 1 换成相应的文本或 JSON 字面量。
把二维数组展平
每张 Invoice 都有自己的 Invoice Items 子数组。要得到一个囊括所有发票全部条目的列表,可以遍历各张发票并把它们的子数组拼接起来。
"Initialize empty array:";
let t := (select 'Invoice Item' where false);
"Iterate over each invoice and add its items:";
for i in Invoices do
t := array(t, i.'Invoice Items')
end;
"Return the flattened list:";
t
工作原理
for i in Invoices do … end遍历每一条 Invoice 记录。array(t, i.'Invoice Items')把t的当前值与该发票中的条目数组拼接起来。- 第一轮迭代追加第一张发票的条目。
- 第二轮迭代追加第二张发票的条目,依此类推。
- 循环结束后,
t就在一个扁平数组中包含了所有发票的所有条目。
现在您可以执行 count(t) 之类的操作来了解条目总数,也可以直接对 t 进行循环或筛选。
