Est-il possible de parcourir tous les éléments d'un tableau associatif ?Je voudrais utiliser une boucle pour parcourir toutes les valeurs d'un tableau associatif.Pour la vie de moi, je ne peux pas trouver la fonction interator pour les tableaux associatifs. Est-il tout simplement impossible de parcourir toutes les valeurs d'un tableau associatif si elles ne correspondent pas à des clés pré-connues ? !
Dans mon tableau associatif, les clés sont des chaînes et les valeurs sont des listes.J'ai besoin de parcourir l'ensemble du tableau associatif et, pour chaque clé, de lire quelque chose à partir de la valeur.
Ceci est mon script (incomplet).Je suis un semi-vétéran de certains langages de programmation mais je suis un noob au script JMP.
Là où je mets des commentaires à l'intérieur de /* */, c'est là qu'il y a du code que je ne sais pas comment faire.Je suis bloqué à /*Pour toutes les parties de lastTests*/ vers le bas, bien que je ne sache pas si le reste de mon script fonctionne car je n'ai pas encore essayé de l'exécuter.
Soit dit en passant, le guide de script JMP contient une très brève section sur les tableaux associatifs et ne vous dit pas comment parcourir les éléments d'un tableau associatif 
S'il vous plaît aidez-moi!
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 : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Toujours délicat.Utiliser evallist() pour le faire en une seule étape.Aussi, au lieu de dire si (a une valeur == 1, dis le si (a une valeur, .Un entier positif est vrai en JSL, 0 est faux.Voici quelques façons de faire ce que vous voulez.Une façon boucle explicitement sur toutes les lignes, l'autre utilise pour chaque ligne .
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 : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Je pense que je l'ai enfin fait fonctionner.J'aimerais pouvoir attribuer des valeurs à une liste dans la même ligne que je l'ai construite et me débarrasser de toutes les commandes Insérer dans.Dois-je vraiment faire ceci :
rowValue = {};
Insert Into(rowValue, :Name("start_t"));
Insert Into(rowValue, :Name("part_id"));
Insert Into(rowValue, Row());
Quand j'ai vraiment envie de faire ça ?
rowValue = {:Name("start_t"), :Name("part_id"), Row()};Avec ce dernier, cependant, la valeur de la liste à l'index 3 est littéralement juste le texte "Row()" !Ne devrait-il pas exécuter la fonction Row() et renvoyer la valeur ? !
Existe-t-il un problème connu dans Windows 10 avec la fenêtre de script incroyablement lente ?
Quoi qu'il en soit, c'est le script sous la forme où il SEMBLE finalement fonctionner (besoin de vérifier entièrement):
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 : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Cool. J'espérais que JMP avait quelque chose comme Try.Je vais essayer Essayer
et comparez son temps d'exécution à Contient lorsque j'obtiens l'heure plus tard.Merci beaucoup pour l'aide.Je posterai des mises à jour quand je les aurai.
Re : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Vous pouvez encapsuler un test simple pour la valeur de la clé dans un essayer() section.Pas sûr de la performance vs contient .
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 : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Alors, savez-vous avec certitude qu'il n'y a aucun moyen de tester un tableau associatif pour voir si une clé existe sans utiliser la fonction Get Keys ? Un tableau associatif génère-t-il toujours une erreur lorsque vous tentez d'accéder à une clé qui n'existe pas encore ?
12 ms va être très problématique, c'est un temps extrêmement long juste pour déterminer si une valeur existe à une certaine clé. Je suis à peu près certain que d'autres langages de script le font à l'échelle de la microseconde ; Je sais que Lua le fait incroyablement vite (par rapport à 12 ms, au moins). Si j'ai affaire à une table de données de 300 000 lignes, cela pourrait représenter environ 300 000 clés. Ainsi, le temps d'exécution pourrait augmenter à (300k/20k)*12 ms = 180 ms. MAIS, cela devrait alors fonctionner environ 300 000 fois, de sorte que le temps d'exécution total devient 15 heures (180 ms * 3e5 = 15 heures). En fait, ce serait probablement environ la moitié de cela, puisque le tableau associatif augmenterait au fur et à mesure que la boucle s'exécute. Mais 7,5 heures, c'est encore trop long.
Cependant, ce n'est peut-être pas la fonction Contient qui grignote la majorité du temps d'exécution (dans les 12 ms) mais la fonction Obtenir les clés ?Dans mon script, je n'aurais même pas besoin d'exécuter Get Keys du tout si je garde juste (en parallèle) une liste séparée de clés que j'avais ajoutées dans le tableau associatif.
Re : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Compris.J'ai fait un test avec un tableau associatif de 20 000 clés.J'ai utilisé une recherche contient pour rechercher chacune des 20 000 clés ; pris 12 secondes.La recherche d'une clé individuelle prend une fraction de seconde.
// 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 : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Oui, mais ce script et ses dérivés que je prévois de faire fonctionner sur une table de données avec bien plus de trois cent mille lignes, chacune avec des centaines de colonnes (si mon ordinateur ne peut pas gérer cela ; sinon, alors j'aurai pour le décomposer, mais la taille de la table pour chaque fragment de base de données sera toujours ÉNORME).
Donc c'est Extrêmement important pour optimiser ce code afin qu'il s'exécute le plus efficacement possible.Exécuter Get Keys sur le tableau associatif, puis rechercher l'énorme liste de dizaines ou de centaines de milliers d'entrées simplement pour voir si la liste renvoyée contient une valeur semble HORRIBLEMENT inefficace alors que tout ce que j'ai à faire est de voir si lastTests[partKey] a une valeur qui lui est assignée ou non !
Re : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Le getkeys La méthode renvoie toutes les clés d'un tableau associatif.
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 : Est-il possible de parcourir tous les éléments d'un tableau associatif ?J'ai également essayé la fonction Is Empty (en changeant également le 1 en 0 dans la comparaison), et cela m'a donné la même erreur.
Re : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Merci Mark, IMO, c'est ainsi que cela devrait fonctionner et c'est la même chose que le fonctionnement de structures de données similaires dans d'autres langages.
Comment tester si un tableau associatif a une valeur affectée à une clé spécifique ? Étant donné que j'attribue des valeurs de clé spécifiques "Char" (identiques à la chaîne ?) Aux listes, j'ai d'abord essayé la fonction Is List, mais cela m'a donné une erreur. C'était mon script:
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 );Et voici l'erreur que je vois dans le journal :
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 : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Sachez qu'il n'y a pas d'ordre dans le contenu du tableau associatif. L'indexation est terminée. C'est la raison pour laquelle les messages First et Next parcourent le tableau. L'utilisation du message Get Values renvoie un résultat ordonné, mais le contenu n'est pas nécessairement dans cet ordre.
Re : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Merci!Je ne connaissais pas le Help->Scripting Index !
Il semble que dans mon cas, j'ai besoin d'utiliser la fonction Get Values (je n'ai pas besoin des clés).
Re : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Pour trouver les fonctions et les messages disponibles pour un tableau associatif, accédez à
Aide==>Index des scripts==>Tableau associatif
Vous y trouverez plusieurs façons de parcourir les clés ou les valeurs en les récupérant dans une liste puis en utilisant une boucle For(), etc. "Suivant" pour parcourir un tableau associatif
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;
);
En outre, à partir de la page 207 du guide de script JSL, plusieurs pages de documentation expliquent comment créer et utiliser des tableaux associatifs dans JMP.
Aide==>Livres==>Guide de script
Re : Est-il possible de parcourir tous les éléments d'un tableau associatif ?Par exemple, voici comment parcourir toutes les valeurs d'une table (nommée "t") en Lua, un langage de script courant :
pour clé, val par paires (t) do
fin
Quel est l'équivalent dans le langage de script JMP pour les tableaux associatifs ?