Obwohl ich gearbeitet habe JMP seit mehr als 10 jahren lerne ich immer noch neue dinge. Zuletzt war es eine neue Sicht auf das Ishikawa-Diagramm und die Macht der Rekursion. Obwohl es beide schon seit Ewigkeiten gibt, habe ich mich erst um sie gekümmert, als ich eine bestimmte Herausforderung hatte. Diese neue Motivation kam, als ich mich entwickelte Geocodierung 2020 , ein Add-In, das eine REST-API für die Kommunikation mit einem Server verwendet. Die Daten, die vom Server kamen, hatten die Form eines JSON-Arrays, das je nach Daten ziemlich groß sein konnte. Einer der versteckten Edelsteine in JMP (oder genauer gesagt in JSL) ist der Befehl Parse JSON(), der ein JSON-Array in eine JSL-Liste oder ein assoziatives Array übersetzt. Es war ein ziemlich guter Ausgangspunkt, aber wenn ich bestimmte Teile der Daten erfassen wollte, musste ich wissen, wie ich sie finden und adressieren konnte. Keine leichte Aufgabe, wenn dieses Array aus mehreren hundert Elementen besteht, die tief in Listen und Arrays gestapelt sind. Also beschloss ich, dieses hilfreiche kleine Programm zu schreiben, stackmole.jsl , um mir einen Überblick über die Datenstruktur zu geben. Und ich wäre kein respektabler JMPler, wenn ich nicht nach einer grafischen Präsentation gesucht hätte.
Jeder Serveraufruf könnte Daten mit einer völlig anderen Tiefe, Breite und Menge liefern. Das Vorhandensein oder Fehlen eines Teils der Daten hängt von den Daten selbst ab. Es ist unmöglich, im Voraus zu wissen, wie diese Datenstruktur aussieht. Ich brauchte ein Programm, das selbst entscheiden konnte, ob es weiter nach Daten suchen sollte, ob es nach der nächsten Liste oder dem nächsten Array suchen sollte oder ob es am Ende war. Rekursion war meine Antwort auf dieses Problem. Ich kenne rekursive Definitionen in der Mathematik, aber wie würde das in einer Datenstruktur funktionieren? Überraschend gut!
Datenstrukturen und Rekursion Schritt für Schritt
Rekursion bedeutet, dass ich dieselbe Regel oder Logik auf das Ergebnis anwende, das ich im vorherigen Schritt erzeugt habe. Die Definition einer Fakultät einer ganzen Zahl ist das bekannteste Beispiel. Die Fakultät einer Zahl ist das Produkt dieser Zahl mit allen kleineren Zahlen bis hinunter zu 1, was bedeutet, dass die Fakultät von 3 oft als 3 geschrieben wird! = 3 * 2 * 1 = 6. Der Skriptleitfaden zeigt die Anweisungen für diese Routine:
myfactorial = Function( {a},
If( a == 1,
1,<BR /> a * Recurse( a - 1 )
)
);
Rekursion kann nur auf eine Funktion angewendet werden; der Befehl steht in der Funktion selbst und ruft diese Funktion mit dem neuen Argument auf. Im Beispiel von 3! wird die Funktion mit 3 als Argument aufgerufen: myfactorial(3). Da 3 ungleich 1 ist, wird die else-Klausel der IF-Anweisung ausgeführt. Dies bedeutet, 3 mit dem Ergebnis von myfactorial (2) zu multiplizieren. Auch das ist nicht gleich 1 und die else-Klausel multipliziert nun 2 mit dem Ergebnis von myfactorial(1). Jetzt gibt es ein Ergebnis; es ist 1.
JMP erinnert sich, dass die offene Aufgabe zuvor darin bestand, 2 mit diesem Ergebnis zu multiplizieren (2 * 1 = 1) und die Aufgabe davor darin bestand, 3 mit dem Rekursionsergebnis zu multiplizieren, das 3 * 2 = 6 ist. Da 3 auf der obersten Ebene war, ist das Ergebnis 6. Man kann sich den Mechanismus vorstellen, wie man eine Treppe hinuntergeht. Bei jedem Schritt wird die offene Aufgabe abgelegt. Das Programm geht so viele Schritte wie nötig nach unten, bis es keine Rekursion mehr gibt. Auf dem Weg zurück nach oben sammelt er alle Aufgaben und landet mit dem Ergebnis im Startgeschoss.
JSL kennt einige Datensammlungen (z. B. Variablen, die viele Werte darstellen). Die Strukturen, die von diesem Programm analysiert werden können, sind Listen und assoziative Arrays. Listen sind durch Kommas getrennte Listen von Elementen wie:
Liste = {"a", "b", 1, 2}
Assoziative Arrays sind Listen von Schlüssel-Wert-Paaren.
assarr = ["a" => "Dies", "b" => "ist", "c" => "a", "d" => "Satz"];
Das erste Element jedes Paares ist der Schlüssel; der zweite ist der Wert. Schlüssel müssen eindeutig sein und werden intern alphabetisch sortiert.
Aufgrund der unterschiedlichen Konzepte benötigt jede Struktur unterschiedliche Befehle, um ihren Inhalt zu ändern oder zu lesen, sie können im Scripting Guide nachgeschlagen werden. Welche Ergebnisse würde der Stack-Maulwurf bei der Analyse einer einfachen Liste erzeugen?
list = {"a1", "b1", "c1"};
stackmole (l);

Die Datentabelle ist die Liste der Gegenstände, die der Maulwurf gefunden hat, als er in die Tiefe der Struktur gebohrt hat. Die Zeilen sind aus der Kinderperspektive zu interpretieren. Das gesamte Set ist eine Liste, wobei das erste Kind (auf Ebene 2) das erste Element in dieser Liste ist. Dieses untergeordnete Element (Zeile 2) sind die Daten und ihr Wert ist „a1“. Daten sind der Endpunkt jeder Reise, das heißt, wenn es kein anderes Element gibt, ist das Element Null.
Informativer ist das Ursache-Wirkungs-Diagramm, das dem Ishikawa-Diagramm in seinem hierarchischen Stil entspricht. Unten stehen die Datenwerte, darüber ihre Indizes in eckigen Klammern. In diesem kleinen Beispiel lautet der Name des gesamten Satzes „list“, wenn Sie also „b1“ erhalten möchten, ist es list [2].
Das parallele Diagramm zeigt, dass sich der gesamte Satz in drei Elemente aufteilt und die Elemente der nächsten Ebene nicht mehr aufgeteilt werden, da sie die Daten enthalten. Während es hilft, kleine Strukturen zu verstehen, zeige ich am Ende dieses Artikels ein farbenfrohes Paralleldiagramm, das nichts hilft.
Die Ergebnisse für ein assoziatives Array unterscheiden sich geringfügig vom Listenbericht, da sie die Namen der Schlüssel enthalten:
sentencearray = ["a" => "This", "b" => "is", "c" => "a", "d" => "sentence"];
stackmole(sentencearray);

Der Typ des gesamten Satzes ist aa, was die Abkürzung für assoziatives Array ist. Der ganze Satz heißt „Sentencearray“; Wenn Sie auf das Wort „Satz“ in diesem Array zugreifen möchten, tun Sie dies mit Satzarray [„d“].
Diese Methode ist einfach, da sie nur eine Struktur mit einem Satz von Elementen verwendet. Aber JMP erlaubt es, diese Strukturen in beliebiger Weise und Tiefe zu stapeln. Sie haben also möglicherweise Listen von assoziativen Arrays von assoziativen Arrays von Listen, … In diesem Beispiel:
array = ["2list1" => {{"4list1_1", "4list1_2", "4list1_3"}, {"4list2_1", "4list2_2"} },
"2list2" => {{"4list3_1", "4list3_2"}, "4element1" } ];
„array“ ist ein assoziatives Array mit zwei Schlüsseln namens „2list1“ und „2list2“. Die Werte jedes Schlüssels sind Listen, wobei die erste Liste wiederum aus zwei Listen besteht, die zweite Liste aus einer Liste und einem Datenelement. Die Ziffern am Anfang jedes Begriffs geben die Tiefe des Stapels an, in dem sich diese Elemente befinden. In der Analogie der Treppe ist es die Anzahl der Stufen, die Sie hinuntergehen müssen, um dieses Element zu erreichen.
In diesem Fall liefert der Stack-Maulwurf folgende Informationen:

Das Bild zeigt nur einen Teil der Datentabelle, die jetzt 21 Zeilen hat. Das Hierarchiediagramm ist fertig. Wenn Sie zum Datenelement 4list3_2 (fett gedruckt) gelangen möchten, lautet der Pfad:
array["2liste2"][1][2]
Unten ist ein Beispiel für einen parallelen Plot, der überhaupt nicht hilft, aber dennoch ein interessantes Muster ergibt:

Das Programm hat viele Kommentare, die die einzelnen Schritte der Analyse erklären und wie die Rekursion angewendet wird.