儘管我曾在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]
下面是一個平行圖的例子,它一點幫助也沒有,但仍然給出了一個有趣的模式:

該程序有許多註釋,解釋了分析的單個步驟以及如何應用遞歸。