Même si j'ai travaillé à JMP depuis plus de 10 ans, j'apprends encore de nouvelles choses. Plus récemment, il s'agissait d'une nouvelle vision du diagramme d'Ishikawa et de la puissance de la récursivité. Bien que les deux existent depuis des lustres, ce n'est que lorsque j'ai eu un défi spécifique que je me suis soucié d'eux. Cette nouvelle motivation est venue lorsque je développais Géocodage 2020 , un complément qui utilise une API REST pour communiquer avec un serveur. Les données, provenant du serveur, se présentaient sous la forme d'un tableau JSON qui pouvait être assez volumineux, selon les données. L'un des joyaux cachés de JMP (ou plus précisément, en JSL), est la commande Parse JSON(), qui traduit un tableau JSON en une liste JSL ou un tableau associatif. C'était un assez bon point de départ, mais quand même, si je voulais saisir des parties spécifiques des données, j'avais besoin de savoir comment les trouver et les traiter. Ce n'est pas une tâche facile si ce tableau est composé de plusieurs centaines d'éléments, profondément empilés dans des listes et des tableaux. J'ai donc décidé d'écrire ce petit programme utile, stackmole.jsl , pour me donner un aperçu de la structure des données. Et, je n'étais pas un JMPer respectable si je ne recherchais pas une présentation graphique.
Chaque appel au serveur peut fournir des données avec une profondeur, une largeur et un volume complètement différents. La présence ou l'absence d'une partie des données dépend des données elles-mêmes. Il est impossible de savoir à l'avance à quoi ressemble cette structure de données. J'avais besoin d'un programme qui puisse décider par lui-même s'il doit continuer à rechercher des données, s'il doit rechercher la liste ou le tableau suivant, ou s'il se trouve à la fin. La récursivité était ma réponse à ce problème. Je connais les définitions récursives en mathématiques, mais comment cela fonctionnerait-il dans une structure de données ? Étonnamment bien !
Structures de données et récursivité pas à pas
La récursivité signifie que j'applique la même règle ou logique au résultat que j'ai produit à l'étape précédente. La définition d'une factorielle d'un nombre entier est l'exemple le plus connu. La factorielle d'un nombre est le produit de ce nombre avec tous les plus petits nombres jusqu'à 1, ce qui signifie que la factorielle de 3 s'écrit souvent 3 ! = 3 * 2 * 1 = 6. Le Guide de script affiche les instructions de cette routine :
myfactorial = Function( {a},
If( a == 1,
1,<BR /> a * Recurse( a - 1 )
)
);
Recurse ne peut être appliqué qu'à une fonction ; la commande se trouve dans la fonction elle-même et appelle cette fonction avec le nouvel argument. Dans l'exemple de 3!, la fonction est appelée avec 3 comme argument : myfactorial(3). Comme 3 n'est pas égal à 1, la clause else de l'instruction IF est exécutée. Cela signifie multiplier 3 avec le résultat de myfactorial (2). Encore une fois, cela n'est pas égal à 1 et la clause else multiplie maintenant 2 avec le résultat de myfactorial(1). Il y a un résultat maintenant; c'est 1.
JMP se souvient que la tâche ouverte précédente consistait à multiplier 2 avec ce résultat (2 * 1 = 1) et que la tâche précédente consistait à multiplier 3 avec le résultat de la récursivité, qui est 3 * 2 = 6. Puisque 3 était au niveau le plus élevé, le résultat est 6. Le mécanisme peut être imaginé comme descendant un escalier. A chaque étape, la tâche ouverte est déposée. Le programme descend autant d'étapes que nécessaire, jusqu'à ce qu'il n'y ait plus de récursivité. En remontant les escaliers, il récupère toutes les tâches et termine à l'étage de départ avec le résultat.
JSL connaît certaines collections de données (par exemple, des variables qui représentent de nombreuses valeurs). Les structures qui peuvent être analysées par ce programme sont des listes et des tableaux associatifs. Les listes sont des listes d'éléments séparés par des virgules tels que :
liste = {"a", "b", 1, 2}
Les tableaux associatifs sont des listes de paires clé-valeur.
assarr = ["a" => "Ceci", "b" => "est", "c" => "a", "d" => "phrase"] ;
Le premier élément de chaque paire est la clé ; le second est la valeur. Les clés doivent être uniques et sont triées en interne par ordre alphabétique.
En raison des différents concepts, chaque structure a besoin de différentes commandes pour modifier ou lire leur contenu, elles peuvent être consultées dans le Guide de script. Quelle sortie la taupe de la pile produirait-elle en analysant une simple liste ?
list = {"a1", "b1", "c1"};
stackmole (l);

La table de données est la liste des éléments que la taupe a trouvés lors de l'exploration de la profondeur de la structure. Les lignes doivent être interprétées du point de vue de l'enfant. L'ensemble complet est une liste, avec le premier enfant (au niveau 2) comme premier élément de cette liste. Cet enfant (ligne 2) est la donnée et sa valeur est "a1". Les données sont le point final de chaque voyage, ce qui signifie que s'il n'y a pas d'autre élément, l'élément est zéro.
Plus informatif est le diagramme de cause à effet, qui est le diagramme d'Ishikawa dans son style hiérarchique. En bas, il y a les valeurs de données au-dessus d'eux leurs indices entre crochets. Dans ce petit exemple, le nom de l'ensemble est « list », donc, si vous voulez obtenir « b1 », c'est list [2].
Le tracé parallèle montre que l'ensemble se divise en trois éléments et que les éléments du niveau suivant ne se divisent plus, puisqu'ils contiennent les données. Bien que cela aide à comprendre les petites structures, à la fin de cet article, je montrerai un diagramme parallèle coloré qui n'aide en rien.
Les résultats d'un tableau associatif diffèrent légèrement du rapport de liste en ce sens qu'ils contiennent les noms des clés :
sentencearray = ["a" => "This", "b" => "is", "c" => "a", "d" => "sentence"];
stackmole(sentencearray);

Le type de l'ensemble est aa, qui est l'abréviation de tableau associatif. L'ensemble est appelé "sentencearray" ; si vous voulez accéder au mot "phrase" dans ce tableau, faites-le avec phrasearray ["d"].
Cette méthode est simple car elle utilise une seule structure avec un ensemble d'éléments. Mais JMP permet d'empiler ces structures de manière arbitraire et en profondeur. Ainsi, vous pouvez avoir des listes de tableaux associatifs de tableaux associatifs de listes, … Dans cet exemple :
array = ["2list1" => {{"4list1_1", "4list1_2", "4list1_3"}, {"4list2_1", "4list2_2"} },
"2list2" => {{"4list3_1", "4list3_2"}, "4element1" } ];
"array" est un tableau associatif avec deux clés nommées "2list1" et "2list2". Les valeurs de chaque clé sont des listes, la première liste étant à nouveau constituée de deux listes, la seconde liste constituée d'une liste et d'un élément de données. Les chiffres au début de chaque terme indiquent la profondeur de la pile où résident ces éléments. Dans l'analogie de l'escalier, c'est le nombre de marches qu'il faut descendre pour atteindre cet élément.
Dans ce cas, la taupe de pile fournit les informations suivantes :

L'image ne montre qu'une partie de la table de données qui compte maintenant 21 lignes. Le schéma hiérarchique est terminé. Si vous souhaitez accéder à l'élément de données 4list3_2 (en gras), le chemin est :
tableau["2list2"][1][2]
Vous trouverez ci-dessous un exemple de tracé parallèle qui n'aide pas du tout, mais qui donne tout de même un motif intéressant :

Le programme contient de nombreux commentaires qui expliquent les différentes étapes de l'analyse et comment la récursivité est appliquée.