¿Es posible iterar a través de todos los elementos en una matriz asociativa?Me gustaría usar un ciclo para iterar a través de todos los valores en una matriz asociativa.Por mi vida, no puedo encontrar la función de interacción para matrices asociativas. ¿Es simplemente imposible recorrer todos los valores en una matriz asociativa si no están en claves conocidas?
En mi matriz asociativa, las claves son cadenas y los valores son listas.Necesito iterar a través de toda la matriz asociativa y, para cada clave, leer algo del valor.
Este es mi script (incompleto).Soy un semi-veterano de algunos lenguajes de programación pero soy un novato en el script JMP.
Donde pongo comentarios dentro de /* */ es donde hay código que no sé cómo hacer.Estoy atascado en /*For all parts in lastTests*/ casi al final, aunque no sé si el resto de mi secuencia de comandos funciona porque aún no he intentado ejecutar ninguna.
Por cierto, la guía de secuencias de comandos JMP tiene una sección muy breve sobre matrices asociativas y no le dice cómo iterar a través de elementos dentro de una matriz asociativa 
¡Por favor ayuda!
dt = Current Data Table();
lastTests = Associative Array();
For Each Row (
partKey = Char(:Name("214:ReadOTP:OTP_Row_40[1]") + 256*:Name("215:ReadOTP:OTP_Row_41[1]") + 256*256*:Name("223:ReadOTP:OTP_Row_49[1]") + 256*256*256*:Name("224:ReadOTP:OTP_Row_4a[1]") + 256*256*256*256*:Name("123:LOG_SETPOINT_SPEA:SPEA_Setpoint[1]"));
rowValue = {:Name("start_t"), :Name("part_id"), Row()};
If (Is List(lastTests[partKey]) == 1,
If ( rowValue[1] > lastTests[partKey][1], //if start_t is later
lastTests[partKey] = rowValue,
//else if
(rowValue[1] == lastTests[partKey][1]) & (rowValue[2] > lastTests[partKey][2]), //if start_t is the same but part_id is larger
lastTests[partKey] = rowValue;
),
//else
lastTests[partKey] = rowValue;
);
);
listOfRowsToSelect = {};
/*For all parts in lastTests*/(
selectedPart = /*get present item*/;
Insert Into(listOfRowsToSelect, selectedPart[3]);
);
dt << Select Rows( listOfRowsToSelect );
/*Invert Selection*/;
/*Hide and Exclude selected rows*/;
dt << Clear Select;
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Todavía complicado.Usar evaluador() para hacerlo en un solo paso.Además, en lugar de decir si (tiene valor == 1, sólo decir si (tiene valor, .Un entero positivo es verdadero en JSL, 0 es falso.Aquí hay algunas maneras de hacer lo que quieras.Una forma recorre todas las filas explícitamente, la otra usa por cada fila .
dt = open("$sample_data\Big Class.jmp");
for (i = 1, i <= nrows(dt), i++,
rowvalue = evallist({column(dt, "age")[i], column(dt, "height")[i], i});
print(rowvalue);
);
current data table(dt);
for each row(
rowvalue = evallist({as column(dt, "age"), as column(dt, "height"), row()});
// This works too
// rowvalue = evallist({:name("age"), :name("height"), row()});
print(rowvalue);
);Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Creo que finalmente lo hice funcionar.Desearía poder asignar valores a una lista en la misma línea en que la construí y deshacerme de todos los comandos Insertar en.¿Realmente tengo que hacer esto?
rowValue = {};
Insert Into(rowValue, :Name("start_t"));
Insert Into(rowValue, :Name("part_id"));
Insert Into(rowValue, Row());
¿Cuando realmente solo quiero hacer esto?
rowValue = {:Name("start_t"), :Name("part_id"), Row()};¡Sin embargo, con este último, el valor de la lista en el índice 3 es literalmente solo el texto "Row()"!¿No debería ejecutar la función Row() y devolver el valor?
¿Hay algún problema conocido en Windows 10 con la ventana Script increíblemente lenta?
De todos modos, este es el script en la forma en que finalmente PARECE estar funcionando (es necesario verificarlo completamente):
dt = Current Data Table();
dt << Clear Select;
lastTests = Associative Array();
//For(i = 1, i <= N Rows(dt), i++,
For Each Row (
//Row() = i;
partKey = Char(:Name("214:ReadOTP:OTP_Row_40[1]") + 256*:Name("215:ReadOTP:OTP_Row_41[1]") + 256*256*:Name("223:ReadOTP:OTP_Row_49[1]") + 256*256*256*:Name("224:ReadOTP:OTP_Row_4a[1]") + 256*256*256*256*Abs(:Name("123:LOG_SETPOINT_SPEA:SPEA_Setpoint[1]")));
rowValue = {};
Insert Into(rowValue, :Name("start_t"));
Insert Into(rowValue, :Name("part_id"));
Insert Into(rowValue, Row());
//rowValue = {:Name("start_t"), :Name("part_id"), i};
hasValue = 0;
try(
junk = lastTests[partKey];
hasValue = 1;
);
If ( hasValue == 1,
If ( rowValue[1] > lastTests[partKey][1], //if start_t is later
lastTests[partKey] = rowValue,
//else if
(rowValue[1] == lastTests[partKey][1]) & (rowValue[2] > lastTests[partKey][2]), //if start_t is the same but part_id is larger
lastTests[partKey] = rowValue;
),
//else
lastTests[partKey] = rowValue;
);
);
listOfRowsToSelect = {};
listOfVals = lastTests << Get Values;
//Show(N Items(listOfVals));
For(i = 1, i <= N Items(listOfVals), i++,
Insert Into(listOfRowsToSelect, listOfVals[i][3]);
//Print(listOfVals[i][3]);
);
dt << Select Rows( listOfRowsToSelect );
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Fresco. Esperaba que JMP tuviera algo como Try.Lo intentaré Intenta
y compare su tiempo de ejecución vs Contiene cuando obtenga el tiempo más tarde.Muchas gracias por la ayuda.Publicaré actualizaciones cuando las tenga.
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Podría envolver una prueba simple para el valor clave en un intentar() sección.No estoy seguro del rendimiento vs contiene .
found = 0;
try(
b = aa["junk"]; // This key is not in the associative array
found = 1;
);
show(found); // Returns 1 if found, 0 if not found. 1 is the same as TRUE, 0 is the same as FALSE
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Entonces, ¿sabe con certeza que no hay forma de probar una matriz asociativa para ver si existe una clave sin usar la función Obtener claves? ¿Una matriz asociativa siempre genera un error cuando intenta acceder a una clave que aún no existe?
12 ms va a ser muy problemático, es un tiempo tremendamente largo solo para determinar si existe un valor en una clave determinada. Estoy bastante seguro de que otros lenguajes de secuencias de comandos hacen esto en escalas de tiempo de microsegundos; Sé que Lua lo hace increíblemente rápido (en comparación con 12 ms, al menos). Si estoy tratando con una tabla de datos de 300 000 filas, entonces en realidad podrían ser alrededor de 300 000 claves. Entonces, el tiempo de ejecución podría aumentar a (300k/20k)*12 ms = 180 ms. PERO, eso tendría que ejecutarse unas 300k veces, por lo que el tiempo total de ejecución se convierte en 15 horas (180 ms * 3e5 = 15 horas). En realidad, probablemente sería aproximadamente la mitad de eso, ya que la matriz asociativa crecería a medida que se ejecuta el bucle. Pero 7,5 horas sigue siendo demasiado tiempo.
Sin embargo, tal vez no sea la función Contiene la que consume la mayor parte del tiempo de ejecución (dentro de los 12 ms), sino la función Obtener claves.En mi secuencia de comandos, ni siquiera tendría que ejecutar Obtener claves en absoluto si solo mantengo (en paralelo) una Lista separada de claves que había agregado a la matriz asociativa.
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Comprendido.Hice una prueba con una matriz asociativa con 20.000 claves.Usé una búsqueda de contenido para buscar cada una de las 20,000 claves; tomó 12 segundos.Buscar una clave individual lleva una fracción de segundo.
// Look for one key
start = hp time();
zlist = aa << getkeys(); // Contains 20,000 keys
a = "xyz9999";
flag = contains(zlist, a);
end = hp time();
show((end - start)/1000000);
// .012 seconds
// Search for all keys using CONTAINS
start = hp time();
for (i = 1, i <= nitems(xlist), i++, // xlist contains the keys in order of creation
x = xlist[i];
b = contains(zlist, x); // zlist comes from getkeys and is not in order of creation
);
end = hp time();
show((end - start)/1000000);
// 12.2 seconds
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Sí, pero planeo hacer que este script y sus derivados necesiten operar en una tabla de datos con más de trescientas mil filas, cada una con cientos de columnas (si mi computadora no puede manejar eso; si no, entonces tendré para dividirlo un poco, pero el tamaño de la tabla para cada fragmento de la base de datos seguirá siendo ENORME).
Así es de importancia crítica para optimizar este código para que se ejecute de la manera más eficiente posible.Ejecutar Get Keys en la matriz asociativa y luego buscar en la enorme lista de decenas o cientos de miles de entradas simplemente para ver si la lista devuelta contiene un valor parece MUY ineficiente cuando todo lo que necesito hacer es ver si lastTests[partKey] tiene un valor asignado o no.
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?El obtener claves El método devuelve todas las claves de una matriz asociativa.
aa = associative array();
aa["One"] = {1, 2, 3};
aa["Two"] = {"a", "b", "c"};
key_list = aa << getkeys();
// Results shown in the log:
{"One", "Two"}Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?También probé la función Is Empty (cambiando el 1 por un 0 en la comparación también), y me dio el mismo error.
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Gracias Mark, en mi opinión, así es como debería funcionar y es lo mismo que funcionan estructuras de datos similares en otros idiomas.
¿Cómo se prueba si una matriz asociativa tiene un valor asignado a una clave específica? Dado que estoy asignando valores clave específicos de "Char" (¿lo mismo que una cadena?) a las listas, primero probé la función Is List, pero me dio un error. Este fue mi guion:
dt = Current Data Table();
lastTests = Associative Array();
For Each Row (
partKey = Char(:Name("214:ReadOTP:OTP_Row_40[1]") + 256*:Name("215:ReadOTP:OTP_Row_41[1]") + 256*256*:Name("223:ReadOTP:OTP_Row_49[1]") + 256*256*256*:Name("224:ReadOTP:OTP_Row_4a[1]") + 256*256*256*256*Abs(:Name("123:LOG_SETPOINT_SPEA:SPEA_Setpoint[1]")));
rowValue = {:Name("start_t"), :Name("part_id"), Row()};
If (Is List(lastTests[partKey]) == 1,
If ( rowValue[1] > lastTests[partKey][1], //if start_t is later
lastTests[partKey] = rowValue,
//else if
(rowValue[1] == lastTests[partKey][1]) & (rowValue[2] > lastTests[partKey][2]), //if start_t is the same but part_id is larger
lastTests[partKey] = rowValue;
),
//else
lastTests[partKey] = rowValue;
);
);
listOfRowsToSelect = {};
listOfVals = lastTests << Get Values;
For(i = 1, i <= nrows(listOfVals), i++,
Insert Into(listOfRowsToSelect, listOfVals[i][3]);
);
dt << Select Rows( listOfRowsToSelect );Y este es el error que veo en el registro:
subscripted key not in map["192344950106"]{1} in access or evaluation of 'partKey' , partKey/*###*/
In the following script, error marked by /*###*/
dt = Current Data Table();
lastTests = Associative Array();
For Each Row(
partKey = Char(
:Name( "214:ReadOTP:OTP_Row_40[1]" ) + 256 *
:Name( "215:ReadOTP:OTP_Row_41[1]" ) + 256 * 256 *
:Name( "223:ReadOTP:OTP_Row_49[1]" ) + 256 * 256 * 256 *
:Name( "224:ReadOTP:OTP_Row_4a[1]" ) + 256 * 256 * 256 * 256 *
Abs( :Name( "123:LOG_SETPOINT_SPEA:SPEA_Setpoint[1]" ) )
);
rowValue = {:start_t, :part_id, Row()};
If( Is List( lastTests[partKey/*###*/] ) == 1,
If(
rowValue[1] > lastTests[partKey][1], lastTests[partKey] = rowValue,
rowValue[1] == lastTests[partKey][1] & rowValue[2] > lastTests[partKey][
2], lastTests[partKey] = rowValue
),
lastTests[partKey] = rowValue
);
);
listOfRowsToSelect = {};
listOfVals = lastTests << Get Values;
For( i = 1, i <= N Rows( listOfVals ), i++,
Insert Into( listOfRowsToSelect, listOfVals[i][3] )
);
dt << Select Rows( listOfRowsToSelect );
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Tenga en cuenta que no hay ordenación de los contenidos de la matriz asociativa. La indexación está descartada. Esa es la razón por la que los mensajes Primero y Siguiente iteran sobre la matriz. El uso del mensaje Obtener valores devuelve un resultado ordenado, pero los contenidos no están necesariamente en este orden.
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?¡Gracias!¡No conocía la Ayuda->Índice de secuencias de comandos!
Parece que en mi caso, necesito usar la función Obtener valores (no necesito las claves).
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Para encontrar las funciones y mensajes disponibles para una matriz asociativa, vaya a
Ayuda==>Índice de secuencias de comandos==>Matriz asociativa
Allí encontrará varias formas de recorrer las claves o valores recuperándolos en una lista y luego usando un bucle For(), etc. "Siguiente" para recorrer una matriz asociativa
Names Default To Here( 1 );
Local(
{aa = [1 => "bun",
2 => "shoe",
3 => "tree",
4 => "door"], x, words = ""},
x = aa << First;
While( !Is Empty( x ),
words = words || aa[x];
x = aa << Next( x );
);
words;
);
Además, a partir de la página 207 de la Guía de secuencias de comandos de JSL, hay varias páginas de documentación sobre cómo crear y utilizar matrices asociativas en JMP.
Ayuda==>Libros==>Guía de secuencias de comandos
Re: ¿Es posible iterar a través de todos los elementos en una matriz asociativa?Como ejemplo, así es como se itera a través de todos los valores en una tabla (llamada "t") en Lua, un lenguaje de programación común:
para clave, val en pares (t) do
fin
¿Cuál es el equivalente en el lenguaje de secuencias de comandos JMP para matrices asociativas?