Aunque he trabajado en JMP durante más de 10 años, sigo aprendiendo cosas nuevas. Más recientemente, fue una nueva vista del diagrama de Ishikawa y el poder de la recursividad. Si bien ambos han existido durante años, no fue hasta que tuve un desafío específico que me preocupé por ellos. Esta nueva motivación vino cuando estaba desarrollando Geocodificación 2020 , un complemento que utiliza una API REST para comunicarse con un servidor. Los datos, provenientes del servidor, estaban en forma de una matriz JSON que podría ser bastante grande, dependiendo de los datos. Una de las gemas escondidas en JMP (o más específicamente, en JSL), es el comando Parse JSON (), que traduce una matriz JSON en una lista JSL o matriz asociativa. Fue un buen punto de partida, pero aun así, si quería obtener partes específicas de los datos, necesitaba saber cómo encontrarlas y abordarlas. No es una tarea fácil si esa matriz está hecha de varios cientos de elementos, profundamente apilados en listas y matrices. Entonces, decidí escribir este pequeño programa útil, stackmole.jsl , para darme una descripción general de la estructura de datos. Y no era un JMPer respetable si no buscaba una presentación gráfica.
Cada llamada al servidor podría entregar datos con una profundidad, ancho y volumen completamente diferentes. La presencia o ausencia de parte de los datos depende de los datos en sí. Es imposible saber de antemano cómo es esa estructura de datos. Necesitaba un programa que pudiera decidir por sí mismo si debería seguir buscando datos, si debería buscar la siguiente lista o matriz, o si estaba al final. La recursividad fue mi respuesta a ese problema. Conozco definiciones recursivas en matemáticas, pero ¿cómo funcionaría eso en una estructura de datos? ¡Sorprendentemente bien!
Estructuras de datos y recursividad paso a paso
La recursividad significa que aplico la misma regla o lógica al resultado que produje en el paso anterior. La definición de factorial de un número entero es el ejemplo más conocido. El factorial de un número es el producto de ese número con todos los números más pequeños hasta 1, lo que significa que el factorial de 3 a menudo se escribe como 3. = 3 * 2 * 1 = 6. La Guía de secuencias de comandos muestra las declaraciones para esa rutina:
myfactorial = Function( {a},
If( a == 1,
1,<BR /> a * Recurse( a - 1 )
)
);
Recurse solo se puede aplicar a una función; el comando está en la propia función y llama a esa función con el nuevo argumento. En el ejemplo de 3 !, la función se llama con 3 como argumento: myfactorial (3). Como 3 no es igual a 1, se ejecuta la cláusula else de la instrucción IF. Esto significa multiplicar 3 con el resultado de myfactorial (2). Nuevamente, eso no es igual a 1 y la cláusula else ahora multiplica 2 con el resultado de myfactorial (1). Ahora hay un resultado; es 1.
JMP recuerda que la tarea abierta antes era multiplicar 2 con este resultado (2 * 1 = 1) y la tarea anterior era multiplicar 3 con el resultado de recursividad, que es 3 * 2 = 6. Como 3 estaba en el nivel más alto, el resultado es 6. Puede imaginarse que el mecanismo baja por una escalera. En cada paso, se deja la tarea abierta. El programa baja tantos pasos como sea necesario, hasta que no hay más recursividad. En su camino de regreso por las escaleras, recoge todas las tareas y termina en el piso de inicio con el resultado.
JSL conoce algunas colecciones de datos (por ejemplo, variables que representan muchos valores). Las estructuras que puede analizar este programa son listas y matrices asociativas. Las listas son listas de elementos separados por comas como:
lista = {"a", "b", 1, 2}
Las matrices asociativas son listas de pares clave-valor.
assarr = ["a" => "Esto", "b" => "es", "c" => "a", "d" => "oración"];
El primer elemento de cada par es la clave; el segundo es el valor. Las claves deben ser únicas y estar ordenadas alfabéticamente internamente.
Debido a los diferentes conceptos, cada estructura necesita diferentes comandos para cambiar o leer su contenido, se pueden buscar en la Guía de secuencias de comandos. ¿Qué resultado produciría el topo de la pila al analizar una lista simple?
list = {"a1", "b1", "c1"};
stackmole (l);

La tabla de datos es la lista de elementos que encontró el topo al profundizar en la profundidad de la estructura. Las filas deben interpretarse desde la perspectiva del niño. Todo el conjunto es una lista, con el primer niño (en el nivel 2) como primer elemento de esa lista. Este hijo (fila 2) es el dato y su valor es "a1". Los datos son el punto final de cada viaje, lo que significa que si no hay otro elemento, el elemento es cero.
Más informativo es el diagrama de causa y efecto, que es el diagrama de Ishikawa en su estilo jerárquico. En la parte inferior, están los valores de los datos por encima de ellos, sus índices entre corchetes. En este pequeño ejemplo, el nombre de todo el conjunto es "lista", por lo que, si desea obtener "b1", es lista [2].
La gráfica paralela muestra que todo el conjunto se divide en tres elementos, y los elementos del siguiente nivel ya no se dividen, ya que contienen los datos. Si bien es útil comprender las estructuras pequeñas, al final de este artículo, mostraré un diagrama paralelo colorido que no ayuda en nada.
Los resultados de una matriz asociativa difieren ligeramente del informe de lista en que contienen los nombres de las claves:
sentencearray = ["a" => "This", "b" => "is", "c" => "a", "d" => "sentence"];
stackmole(sentencearray);

El tipo del conjunto completo es aa, que es la abreviatura de matriz asociativa. El conjunto completo se denomina "arreglo de frases"; si desea acceder a la palabra "oración" en esa matriz, hágalo con la matriz de oraciones ["d"].
Este método es sencillo ya que usa una sola estructura con un conjunto de elementos. Pero JMP permite apilar estas estructuras de forma arbitraria y en profundidad. Por lo tanto, puede tener listas de matrices asociativas de matrices asociativas de listas, ... En este ejemplo:
array = ["2list1" => {{"4list1_1", "4list1_2", "4list1_3"}, {"4list2_1", "4list2_2"} },
"2list2" => {{"4list3_1", "4list3_2"}, "4element1" } ];
"Matriz" es una matriz asociativa con dos claves denominadas "2list1" y "2list2". Los valores de cada clave son listas, la primera lista nuevamente consta de dos listas, la segunda lista consta de una lista y un elemento de datos. Los números al comienzo de cada término indican la profundidad de la pila donde residen esos elementos. En la analogía de la escalera, es la cantidad de escalones que debe bajar para llegar a este elemento.
En este caso, el topo de la pila entrega la siguiente información:

La imagen muestra solo una parte de la tabla de datos que ahora tiene 21 filas. El diagrama de jerarquía está completo. Si desea acceder al elemento de datos 4list3_2 (en negrita), la ruta es:
matriz ["2list2"] [1] [2]
A continuación se muestra un ejemplo de una trama paralela que no ayuda en absoluto, pero que aún da un patrón interesante:

El programa tiene muchos comentarios que explican los pasos individuales del análisis y cómo se aplica la recursividad.