連想配列内のすべての要素を反復処理することは可能ですか?ループを使用して、連想配列内のすべての値を反復処理したいと考えています。私は一生、連想配列のインターレーター関数を見つけることができません。 既知のキーにない場合、連想配列内のすべての値をステップ実行することは単純に不可能なのでしょうか?
私の連想配列では、キーは文字列であり、値はリストです。連想配列全体を反復処理し、キーごとに値から何かを読み取る必要があります。
これは私の(不完全な)スクリプトです。私はいくつかのプログラミング言語については準ベテランですが、JMP スクリプトについては初心者です。
/* */ 内にコメントを入れた場所には、やり方がわからないコードがあります。一番下近くの /*For all Parts in lastTests*/ で行き詰まっていますが、まだスクリプトを実行していないので残りのスクリプトが機能するかどうかはわかりません。
ちなみに、JMP スクリプト ガイドには連想配列に関する非常に短いセクションがあり、連想配列内の要素を反復処理する方法については説明されていません 
助けてください!
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: 連想配列内のすべての要素を反復処理することは可能ですか?まだ難しい。使用evalist()ワンステップで実行できます。また、言う代わりに、 if (値 == 1 の場合、言うだけif (値がある、 。JSL では正の整数は True、0 は false です。ここでは、やりたいことを実現するいくつかの方法を紹介します。一方の方法ではすべての行を明示的にループし、もう一方の方法では各行ごとに。
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: 連想配列内のすべての要素を反復処理することは可能ですか?ようやく機能するようになったと思います。リストを作成したのと同じ行でリストに値を代入し、すべての Insert Into コマンドを削除できればいいのにと思います。本当にこれを行う必要がありますか:
rowValue = {};
Insert Into(rowValue, :Name("start_t"));
Insert Into(rowValue, :Name("part_id"));
Insert Into(rowValue, Row());
本当にこれをやりたいときは?
rowValue = {:Name("start_t"), :Name("part_id"), Row()};ただし、後者の場合、インデックス 3 のリストの値は文字通り単なるテキスト「Row()」です。Row() 関数を実行して値を返すべきではないでしょうか?!
Windows 10 には、スクリプト ウィンドウが非常に遅いという既知の問題がありますか?
とにかく、これは最終的に動作しているように見える形式のスクリプトです (完全に検証する必要があります)。
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: 連想配列内のすべての要素を反復処理することは可能ですか?いいね。 JMP に Try のような機能があることを期待していました。試してみます 試してみます:)後で時間を取得したときに、その実行時間と Contains を比較します。大変お世話になりありがとうございました。最新情報があれば投稿します。
Re: 連想配列内のすべての要素を反復処理することは可能ですか?キー値の簡単なテストをラップすることができます。試す()セクション。パフォーマンスがわからない vs含まれています。
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: 連想配列内のすべての要素を反復処理することは可能ですか?では、Get Keys 関数を使用せずに、連想配列をテストしてキーが存在するかどうかを確認する方法はないことをご存知ですか? まだ存在しないキーにアクセスしようとすると、連想配列は常にエラーを生成しますか?
12 ミリ秒という時間は非常に問題になります。これは、特定のキーに値が存在するかどうかを判断するだけでも非常に長い時間です。 他のスクリプト言語もこれをマイクロ秒の時間スケールで実行していると私は確信しています。 Lua が信じられないほど高速に実行できることはわかっています (少なくとも 12 ミリ秒と比較して)。 300k 行のデータ テーブルを扱っている場合、実際には約 300k のキーになる可能性があります。 したがって、実行時間は (300k/20k)*12 ミリ秒 = 180 ミリ秒に増加する可能性があります。ただし、約 30 万回実行する必要があるため、合計実行時間は 15 時間になります (180 ミリ秒 * 3e5 = 15 時間)。 実際には、ループが実行されるにつれて連想配列が増加するため、おそらくその約半分になります。 しかし、それでも7.5時間は長すぎます。
しかし、実行時間 (12 ミリ秒以内) の大部分を費やしているのは、Contains 関数ではなく、Get Keys 関数ではないでしょうか?私のスクリプトでは、Get Keys を実行する必要さえありません。まったく連想配列に追加したキーの別のリストを(並行して)保持する場合。
Re: 連想配列内のすべての要素を反復処理することは可能ですか?了解した。20,000 個のキーを含む連想配列でテストを行いました。私は包含検索を使用して 20,000 個のキーをそれぞれ検索しました。 12秒かかりました。個々のキーの検索にはほんの数秒かかります。
// 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: 連想配列内のすべての要素を反復処理することは可能ですか?はい、ただし、このスクリプトと作成予定の派生スクリプトは、行数が 30 万をはるかに超え、各行に数百の列があるデータ テーブルを操作する必要があります (コンピューターが処理できない場合は、そうでない場合は、ある程度分割しますが、各データベース フラグメントのテーブル サイズは依然として巨大になります)。
それで、そうです。極めて重要な可能な限り効率的に実行されるようにこのコードを最適化します。連想配列で Get Keys を実行し、数万または数十万のエントリの巨大なリストを検索します。単にlastTests[partKey] に値が割り当てられているかどうかを確認するだけでよいのに、返されたリストに値が含まれているかどうかを確認するのは、ひどく効率が悪いように思えます。
Re: 連想配列内のすべての要素を反復処理することは可能ですか?のキーを取得するこのメソッドは、連想配列のすべてのキーを返します。
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: 連想配列内のすべての要素を反復処理することは可能ですか?また、Is Empty 関数 (比較で 1 を 0 に切り替える) も試してみましたが、同じエラーが発生しました。
Re: 連想配列内のすべての要素を反復処理することは可能ですか?ありがとう、Mark、IMO、これはそのように動作するべきであり、他の言語の同様のデータ構造がどのように動作するかと同じです。
連想配列の値が特定のキーに割り当てられているかどうかをテストするにはどうすればよいでしょうか? 特定の「Char」(文字列と同じ?)キー値をリストに割り当てているため、最初に Is List 関数を試しましたが、エラーが発生しました。 これは私のスクリプトです:
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 );そして、これがログに表示されるエラーです。
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: 連想配列内のすべての要素を反復処理することは可能ですか?連想配列の内容には順序がないことに注意してください。 インデックス作成が終了しました。 これが、First メッセージと Next メッセージが配列に対して反復処理される理由です。 Get Values メッセージを使用すると、順序付けされた結果が返されますが、内容は必ずしもこの順序であるとは限りません。
Re: 連想配列内のすべての要素を反復処理することは可能ですか?ありがとう!「ヘルプ」->「スクリプト索引」については知りませんでした。
私の場合、Get Values 関数を使用する必要があるようです (キーは必要ありません)。
Re: 連想配列内のすべての要素を反復処理することは可能ですか?連想配列で使用できる関数とメッセージを見つけるには、次の場所に移動してください。
ヘルプ==>スクリプトインデックス==>連想配列
ここでは、キーや値をリストに取得して For() ループなどを使用してループするいくつかの方法が見つかります。以下は、「First」と「First」を使用して、スクリプト索引に記載されている例から直接取得した例です。 「次へ」は連想配列をループします。
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;
);
また、『JSL Scripting Guide』の 207 ページ以降には、JMP で連想配列を作成および使用する方法に関するドキュメントが数ページあります。
ヘルプ==>書籍==>スクリプトガイド
Re: 連想配列内のすべての要素を反復処理することは可能ですか?例として、一般的なスクリプト言語である Lua でテーブル (「t」という名前) 内のすべての値を反復処理する方法を次に示します。
key、val のペア (t) の場合
<もの>
終わり
JMP スクリプト言語で連想配列に相当するものは何ですか?