尽管我曾在JMP 10 多年来,我仍在学习新事物。 最近,这是对石川图和递归力量的新看法。 虽然两者都存在了很长时间,但直到我遇到一个具体的挑战时,我才开始关心它们。 这个新的动力是在我开发的时候来的地理编码 2020 ,一个使用 REST API 与服务器通信的插件。 来自服务器的数据采用 JSON 数组的形式,根据数据的不同,该数组可能非常大。 隐藏的宝石之一JMP (或更具体地说,在 JSL 中)是命令 Parse JSON(),它将 JSON 数组转换为 JSL 列表或关联数组。 这是一个很好的起点,但是,如果我想获取数据的特定部分,我需要知道如何查找和处理它们。 如果该数组由数百个项目组成,并深深地堆叠在列表和数组中,这不是一件容易的事。 所以,我决定编写这个有用的小程序,堆栈摩尔.jsl , 给我一个数据结构的概述。 而且,如果我不寻找图形表示,我就不是一个受人尊敬的 JMPer。
每个服务器调用都可以传递深度、宽度和体积完全不同的数据。 部分数据的存在与否取决于数据本身。 不可能事先知道该数据结构是什么样的。 我需要一个程序,它可以自己决定是否应该继续查找数据,是否应该查找下一个列表或数组,或者它是否在末尾。 递归是我对那个问题的回答。 我知道数学中的递归定义,但它在数据结构中如何工作? 出乎意料的好!
数据结构和递归一步一步
递归意味着我将相同的规则或逻辑应用于我之前生成的结果。 整数的阶乘的定义是最广为人知的例子。 一个数的阶乘是该数与所有小于1的数的乘积,也就是说3的阶乘常写成3! = 3 * 2 * 1 = 6。 脚本指南显示了该例程的语句:
myfactorial = Function( {a},
If( a == 1,
1,<BR /> a * Recurse( a - 1 )
)
);
递归只能应用于函数;该命令位于函数本身中,并使用新参数调用该函数。 在 3! 的示例中,函数以 3 作为参数调用:myfactorial(3)。 由于 3 不等于 1,因此执行 IF 语句的 else 子句。 这意味着将 3 与 myfactorial (2) 的结果相乘。 同样,它不等于 1,else 子句现在将 2 乘以 myfactorial(1) 的结果。 现在有结果了;它是 1。
JMP 记得之前的开放任务是将 2 乘以这个结果 (2 * 1 = 1),之前的任务是将 3 乘以递归结果,即 3 * 2 = 6。 由于 3 处于最顶层,因此结果为 6。 该机制可以想象为下楼梯。 在每一步中,打开的任务都会被放下。 程序会根据需要执行尽可能多的步骤,直到不再有递归为止。 在返回楼梯的路上,它收集了所有任务,并以结果结束了起始楼层。
JSL 知道一些数据集合(例如,表示许多值的变量)。 该程序可以分析的结构是列表和关联数组。 列表是逗号分隔的元素列表,例如:
列表 = {"a", "b", 1, 2}
关联数组是键值对的列表。
assarr = ["a" => "这个", "b" => "是", "c" => "a", "d" => "句子"];
每对的第一个元素是键;第二是价值。 键必须是唯一的,并且在内部按字母顺序排序。
由于概念不同,每个结构需要不同的命令来改变或读取它们的内容,它们可以在脚本指南中查找。 stack mole 通过分析一个简单的列表会产生什么输出?
list = {"a1", "b1", "c1"};
stackmole (l);

数据表是地鼠在深入结构深处时发现的项目列表。 这些行将从儿童的角度来解释。 整个集合是一个列表,第一个孩子(在第 2 层)是该列表中的第一项。 这个孩子(第 2 行)是数据,它的值为“a1”。 数据是每一次旅程的终点,这意味着如果没有其他项目,则该项目为零。
提供更多信息的是因果图,它是分层样式的石川图。 在底部,方括号中的索引上方是数据值。 在这个小例子中,整个集合的名称是“list”,所以,如果你想得到“b1”,它就是list[2]。
平行图显示整个集合分成三个元素,下一级元素不再分裂,因为它们包含数据。 虽然它有助于理解小结构,但在本文末尾,我将展示一个色彩缤纷的平行图,但没有任何帮助。
关联数组的结果与列表报告略有不同,因为它们包含键的名称:
sentencearray = ["a" => "This", "b" => "is", "c" => "a", "d" => "sentence"];
stackmole(sentencearray);

整个集合的类型是aa,是associative array的简称。 整个集合称为“sentencearray”;如果您想访问该数组中的单词“sentence”,请使用 sentencearray [“d”]。
这种方法很简单,因为它只使用一个结构和一组元素。 但 JMP 允许以任意方式和深度堆叠这些结构。 所以,你可能有列表的关联数组的关联数组列表,...... 在这个例子中:
array = ["2list1" => {{"4list1_1", "4list1_2", "4list1_3"}, {"4list2_1", "4list2_2"} },
"2list2" => {{"4list3_1", "4list3_2"}, "4element1" } ];
“array”是一个关联数组,有两个名为“2list1”和“2list2”的键。 每个键的值都是列表,第一个列表同样由两个列表组成,第二个列表由一个列表和一个数据元素组成。 每一项开头的数字表示这些元素所在的堆栈深度。 在楼梯的类比中,它是您需要向下走才能到达该元素的步数。
在这种情况下,stack mole 传递以下信息:

图片仅显示了现在有 21 行的数据表的一部分。 层次结构图已完成。 如果要获取数据元素 4list3_2(粗体),路径为:
数组[“2list2”][1][2]
下面是一个平行图的例子,它一点帮助也没有,但仍然给出了一个有趣的模式:

该程序有许多注释,解释了分析的单个步骤以及如何应用递归。