数値リストのリスト内の要素を文字に変換する最速の方法は何ですか?この課題は、コミュニティで見つかった質問の拡張です。私は 8 つのアプローチをテストすることにしました。3 つの反復メソッド ( For 、 For Each 、およびTransform Each )、4 つの非反復メソッド (テーブル操作、式、 Words + 式、およびRegex )、および 1 つのハイブリッド ( Words + Transform Each ) です。これらのメソッドのうち、正規表現や式を含まない 5 つのメソッドが、リンクされた投稿で検討されました。 WordとRegexを使用する方法は、文字列操作の副作用を悪用するという点で少しチートです。具体的には、あらゆるデータ構造を文字列に変換し、それに応じて解析できます。このアプローチが正当であると感じるかどうかは読者に任せます。私はそれを見て眉をひそめる人を何人か知っています。
スペース充填デザインを使用して、リストの数、リストの要素の数、リストの要素の数が等しいか等しくないか、数値の種類: 整数か浮動小数点という 4 つの要素を調べました。設計はリストのリスト – Experimental Runs.JMPにあります。元の設計生成の小数値は四捨五入されています。実行ごとに 10 回の複製を作成しました。実験の実行に使用したコードはRun list of list Experiment.JSLにあり、結果はList of list results.JMP にあります。 Regexを使用した予備実行は非常に遅かったため、検討から除外されました。
メソッドを比較するために、実行とレプリケーションによる各メソッドの順位と、実験実行内のすべてのレプリケーションの実行時間と実行時間の中央値の差を計算します。小さいほど良いです。以下のグラフは、 Transform Each 、テーブル操作、およびWordsメソッドが優れていることを示しています。実際の時間差は小さいですが (値はマイクロ秒単位です)、これらの方法は一貫して上位にランクされており、変動も少なくなります。


4 つの方法に違いがあるかどうかを確認するために、より大きなリスト ( List of lists big – Experimental Runs.JMPおよびList of lists big results.JMP ) を使用して実験を再実行しました。実行時間の中央値との時間差を見ると、アイテムの総数が増加するにつれて、 Transform Eachとテーブル操作のパフォーマンスが最も高くなることがわかります。 Transform Each はJMP 16で導入されたばかりであり、テーブル操作はまだ JMP 15 を使用している人にとって良いソリューションを提供するため、これは幸運な結果です。

2 番目の課題では、リストのリストを転置するように依頼しました。リストの転置リストは、入力リストのすべての最初の要素を最初の出力リストに収集し、2番目の入力要素を 2番目の出力リストに収集します。入力にn個のリストがある場合、各出力リストにはn個の要素が含まれます。出力リストの数は、各リスト内の項目の最大数と等しくなります。入力リストの数は簡単に判断できますが、出力リストの数を決定するには、各入力リスト内の項目を数える必要があります。これは必要ですか?それはプロセスの高速化につながりますか?
この質問に答え、特定のメソッドをテストするために、別のスペース充填デザインを実行しました。その中で、私は 3 つの反復メソッド ( For 、 For Each 、およびTransform Each ) をそれぞれ 2 つのアプローチを使用して調べました。 1 つは出力を構築する前に出力リストの数を計算し、入力を 2 回ループする必要があり、もう 1 つは次を使用して出力を構築します。入力に対する単一のループ。さらに、テーブル操作の使用も検討しました。 6 つの異なるリスト要素タイプ (整数、浮動小数点、1 文字、8 文字、15 文字、および可変幅文字 (最大長 15))、および固定および可変 (内部) リスト長が検討されました。
最初のコーディング中に、 Repeatや式を使用して不足している値を出力に事前に設定するよりも、空のリストから始めてInsert Intoを使用して出力リストを作成する方が速いことがわかりました。 Prebuild または Insert.JSLのコードを使用して、これを自分で確認できます。 2 番目の発見は、 Transform EachとFor Eachに関するものでした。これらの関数に慣れていない方のために説明すると、これらの関数は、サイズを指定せずにリスト、行列、または連想配列を反復処理できるという点で、標準のForループや While ループとは少し動作が異なります。これにより、コードがもう少しコンパクトでクリーンになります。これらの関数の基本的な呼び出しの構造は次のとおりです。
fnName ({ indValue , ind },コンテナ,本体)
ここで、 fnNameはFor EachまたはTransform Each 、 indValueはインデックスindのコンテナーの値、 containerは行列、リスト、または連想配列、 bodyはコードの本体です。大きな容器を扱うときは注意が必要です。大きなデータ構造をコンテナーまたはindValueとして使用すると、実行速度が大幅に低下します。この例は、「 For Each および Transform Each.JSL の使用」で説明されています。この中で、リストのリストの各リスト内の項目の数を数えています。コードの最初の 2 つのブロックは、問題をコーディングする方法に対応しています。最初のブロックでは各サブリストを入力値として使用し、2 番目のブロックではサブリストにインデックスを付けます。これを、 aListへのインデックスが明示的に作成され、ループ内で使用される 3 番目のブロックと比較してください。 aListのサイズに応じて、処理速度が 100 倍以上向上する可能性があります。 Transform Eachはさらに高速で、結果の値を返すことができます。ブロック 4 と 5 は、出力データ構造が入力コンテナーに使用されるデータ構造と同じになることを示しています。出力データ構造のタイプを制御するオプションのOutput()引数があります。
さまざまな転置方法をテストするためのコードは、 Transpose lists.JSLにあります。上記と同様に、空間充填設計を使用して、さまざまな条件下での出力を比較しました。上記のコードとは異なり、繰り返しごとに新しいデータ構造が作成されます。最初の 3 つのメソッドは、入力を読み取り、単一のブロックで出力を構築します。次の 3 つは、入力を処理する前に、まず出力リストのサイズを事前に決定します。最後から 2 番目のメソッドはテーブル操作を使用し、最後の Transform Each は出力値を使用するように構造化されています。

出力リストのサイズを事前に決定しておくと、これを単一のブロックで実行するよりも高速であることがわかりました。 Transform Eachのさまざまな実装では、出力値を操作することで速度が向上することがわかります。結果はTranspose results.JMPにあります。 For Each 、 Transform Each (2番目の実装)、およびテーブル操作を比較するより大きなリストの実験は、 Transpose の結果 big.JMPにあります。この結果は、テーブル操作が一般に他の 2 つのアプローチよりも優れていることを示唆しています。

私たちが発見したことを要約すると、次のようになります。
- 時間ごと: Each < For Each < Forを変換します
- 列の式が関与しない場合、テーブルの操作は非常に高速になります。以前の投稿で、列数式はその複雑さに応じて、反復または式の方が有利な点まで操作が遅くなる可能性があることを見てきました。
この課題では、これまでに経験したような典型的なフィードバックは得られなかったので、もっと良いアプローチがあると確信しています。ぜひご意見をお聞かせください。来月も新たな挑戦を目指してください。