È possibile scorrere tutti gli elementi in un array associativo?Vorrei utilizzare un ciclo per scorrere tutti i valori in un array associativo.Per la vita di me, non riesco a trovare la funzione di interazione per gli array associativi. È semplicemente impossibile scorrere tutti i valori in un array associativo se non sono in chiavi preconosciute?!
Nel mio array associativo, le chiavi sono stringhe ei valori sono liste.Devo scorrere l'intero array associativo e, per ogni chiave, leggere qualcosa dal valore.
Questa è la mia sceneggiatura (incompleta).Sono un semi-veterano di alcuni linguaggi di programmazione ma sono un principiante dello script JMP.
Dove metto i commenti all'interno di /* */ è dove c'è il codice che non so come fare.Sono bloccato su /*For all parts in lastTests*/ vicino alla fine, anche se non so se il resto del mio script funziona perché non ho ancora provato a eseguirlo.
A proposito, la guida allo scripting di JMP ha una sezione molto breve sugli array associativi e non ti dice come scorrere gli elementi all'interno di un array associativo 
Per favore aiuto!
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;
Ri: è possibile scorrere tutti gli elementi in un array associativo?Ancora complicato.Utilizzo vallist() per farlo in un solo passaggio.Inoltre, invece di dire se (havalore == 1, basta dire se (havalore, .Un numero intero positivo è vero in JSL, 0 è falso.Ecco alcuni modi per fare quello che vuoi.Un modo esegue il loop su tutte le righe in modo esplicito, l'altro utilizza per ogni riga .
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);
);Ri: è possibile scorrere tutti gli elementi in un array associativo?Penso di averlo fatto funzionare finalmente.Vorrei poter assegnare valori a un elenco nella stessa riga in cui l'ho costruito e sbarazzarmi di tutti i comandi Inserisci in.Devo davvero fare questo:
rowValue = {};
Insert Into(rowValue, :Name("start_t"));
Insert Into(rowValue, :Name("part_id"));
Insert Into(rowValue, Row());
Quando voglio davvero solo fare questo?
rowValue = {:Name("start_t"), :Name("part_id"), Row()};Con quest'ultimo, tuttavia, il valore della lista all'indice 3 è letteralmente solo il testo "Row()"!Non dovrebbe eseguire la funzione Row() e restituire il valore?!
C'è un problema noto in Windows 10 con la finestra Script incredibilmente lenta?
Ad ogni modo, questo è lo script nella forma in cui finalmente SEMBRA funzionare (è necessario verificare 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 );
Ri: è possibile scorrere tutti gli elementi in un array associativo?Freddo. Speravo che JMP avesse qualcosa come Try.Proverò Prova
e confronta il suo tempo di esecuzione rispetto a Contains quando avrò il tempo in seguito.Grazie mille per l'aiuto.Pubblicherò gli aggiornamenti quando li avrò.
Ri: è possibile scorrere tutti gli elementi in un array associativo?Potresti avvolgere un semplice test per il valore della chiave in a Tentativo() sezione.Non sono sicuro delle prestazioni 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
Ri: è possibile scorrere tutti gli elementi in un array associativo?Quindi, sai per certo che non c'è modo di testare un array associativo per vedere se esiste una chiave senza usare la funzione Ottieni chiavi? Un array associativo genera sempre un errore quando si tenta di accedere a una chiave che non esiste ancora?
12 ms sarà molto problematico, ovvero un tempo tremendamente lungo solo per determinare se esiste un valore in una determinata chiave. Sono abbastanza certo che altri linguaggi di scripting lo facciano in tempi di microsecondi; So che Lua lo fa in modo incredibilmente veloce (rispetto a 12 ms, almeno). Se ho a che fare con una tabella di dati di 300.000 righe, in realtà potrebbero essere circa 300.000 chiavi. Quindi il tempo di esecuzione potrebbe aumentare fino a (300k/20k)*12 ms = 180 ms. MA, ciò dovrebbe quindi essere eseguito circa 300k volte, quindi il tempo di esecuzione totale diventa 15 ore (180 ms * 3e5 = 15 ore). In realtà, probabilmente sarebbe circa la metà, poiché l'array associativo crescerebbe durante l'esecuzione del ciclo. Ma 7,5 ore sono ancora troppe.
Tuttavia, forse non è la funzione Contains che mastica la maggior parte del tempo di esecuzione (entro i 12 ms) ma la funzione Get Keys?Nel mio script, non dovrei nemmeno eseguire Get Keys affatto se mantengo (in parallelo) un elenco separato di chiavi che ho aggiunto all'array associativo.
Ri: è possibile scorrere tutti gli elementi in un array associativo?Inteso.Ho fatto un test con un array associativo con 20.000 chiavi.Ho usato una ricerca contiene per cercare ciascuna delle 20.000 chiavi; ci sono voluti 12 secondi.La ricerca di una singola chiave richiede una frazione di secondo.
// 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
Ri: è possibile scorrere tutti gli elementi in un array associativo?Sì, ma questo script e i suoi derivati che ho intenzione di fare devono operare su una tabella di dati con oltre trecentomila righe, ciascuna con centinaia di colonne (se il mio computer non è in grado di gestirlo; in caso contrario, avrò per spezzarlo un po ', ma la dimensione della tabella per ogni frammento di database sarà comunque ENORME).
Così è criticamente importante per ottimizzare questo codice in modo che venga eseguito nel modo più efficiente possibile.Esecuzione di Get Keys sull'array associativo e quindi ricerca dell'enorme elenco di decine o centinaia di migliaia di voci semplicemente per vedere se l'elenco restituito contiene un valore sembra ORRIBILMENTE inefficiente quando tutto ciò che devo fare è vedere se lastTests[partKey] ha un valore assegnato o meno!
Ri: è possibile scorrere tutti gli elementi in un array associativo?IL getkeys Il metodo restituisce tutte le chiavi per un array associativo.
aa = associative array();
aa["One"] = {1, 2, 3};
aa["Two"] = {"a", "b", "c"};
key_list = aa << getkeys();
// Results shown in the log:
{"One", "Two"}Ri: è possibile scorrere tutti gli elementi in un array associativo?Ho anche provato la funzione Is Empty (passando da 1 a 0 anche nel confronto) e mi ha dato lo stesso errore.
Ri: è possibile scorrere tutti gli elementi in un array associativo?Grazie Mark, IMO, è così che dovrebbe funzionare ed è lo stesso di come funzionano strutture di dati simili in altre lingue.
Come si verifica se un array associativo ha un valore assegnato a una chiave specifica? Poiché sto assegnando specifici valori di chiave "Carattere" (lo stesso della stringa?) Alle liste, ho prima provato la funzione Is List, ma mi ha dato un errore. Questa era la mia sceneggiatura:
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 );E questo è l'errore che vedo nel 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 );
Ri: è possibile scorrere tutti gli elementi in un array associativo?Tieni presente che non esiste un ordinamento dei contenuti dell'array associativo. L'indicizzazione è fuori. Questo è il motivo per cui i messaggi First e Next si ripetono sull'array. L'utilizzo del messaggio Ottieni valori restituisce un risultato ordinato, ma i contenuti non sono necessariamente in questo ordine.
Ri: è possibile scorrere tutti gli elementi in un array associativo?Grazie!Non sapevo dell'Help->Scripting Index!
Sembra che nel mio caso devo usare la funzione Ottieni valori (non ho bisogno delle chiavi).
Ri: è possibile scorrere tutti gli elementi in un array associativo?Per trovare le funzioni e i messaggi disponibili per un array associativo, vai a
Aiuto==>Indice scripting==>Array associativo
Lì troverai diversi modi per scorrere le chiavi o i valori recuperandoli in un elenco e quindi utilizzando un ciclo For (), ecc. Di seguito è riportato un esempio preso direttamente dagli esempi forniti nell'indice di scripting utilizzando "Primo" e "Next" per scorrere un array associativo
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;
);
Inoltre, a partire da pagina 207 nella JSL Scripting Guide ci sono diverse pagine di documentazione su come creare e utilizzare array associativi in JMP
Aiuto==>Libri==>Guida allo scripting
Ri: è possibile scorrere tutti gli elementi in un array associativo?Ad esempio, questo è il modo in cui si ripetono tutti i valori in una tabella (denominata "t") in Lua, un linguaggio di scripting comune:
per chiave, val in coppia (t) do
FINE
Qual è l'equivalente nel linguaggio di scripting JMP per gli array associativi?