9

2次元配列があるとしましょう:vectors[x][y]、そして初期配列構造は次のようになります:

vectors = [    
 [0, 0, 0, 0, 0,],
 [0, 0, 0, 0, 0,],
 [0, 0, 0, 0, 0,],
 [0, 0, 0, 0, 0,],
 [0, 0, 0, 0, 0,]
]

いくつかの計算の後、配列内のデータはランダム化されます。アレイを初期状態に戻すための最速の方法と最も効率的な方法は何ですか?

上記のゼロ化された配列をハードコーディングして、それに等しいベクトルを再び設定できることは知っていますが、次のようなアルゴリズムも知っています。

for (var x = 0; x < vectors.length; x++) {
    for (var y = 0; y < vectors[x].length; y++) {
        vectors[x][y] = 0;
    }

}

O(x * y)です。

では、どちらがより良い方法ですか?そして、これを解決するためのより良い、さらに速く/より効率的な方法はありますか?

そして、任意の長さの多次元配列をゼロにする一般的なケースでは、これが最良の方法ですか?(重要な場合はJavaScriptで作業しています)

4

4 に答える 4

3

これが私の2セントです:

最速のパフォーマンスを得るために、元のアレイのクリーンなコピーを保持することにします。参照されたハードコードされたコピーを保持することができます

var vectorsOrig = [    
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0]
];

または、スライスを使用して初期配列の動的クリーンクローンを実行します((ディープコピーの場合は再帰的に):

var clonedVectors = [0, 0, 0, 0, 0].slice(0);

とにかく、ベクトル参照を元のコピーにリセットするアプローチを取ることは、各ノードを循環してリセットするよりも高速です。古いベクトル配列オブジェクトが参照されなくなった場合、JavaScriptはそれをガベージコレクションします。

そうは言っても、問題は毎回クリーンコピーを取得することです。一度ハードコーディングされたインスタンスがあると、1つのクリーンなコピーが得られ、その後クローンを作成する必要があります。また、リセットオプションと同様のforループを介して動的生成を開始する必要もありません。私のアドバイスは、ハードコードされた、または初期化された新しい配列を返すだけのクローン関数を作成することです。

function newVector() {
    return [    
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0]
    ];
}
var vector = newVector();
vector[1][2] = 11;
console.dir(vector);
vector = newVector();  // your old array will be garbage-collected if no longer referenced by any other reference
console.dir(vector);

理想的には、さまざまなアプローチのベンチマークを行うのが最善です。

編集 ベガの入力のおかげで、私は3つのアプローチをテストするために彼のテストを変更しました。ChromeとIE9では、このソリューションが最速のようです。FF(15.0.1)では、手動の反復が高速に見えます(FFではメモリの割り当て/管理が遅くなる可能性があります)。http://jsperf.com/array-zero-test/2

于 2012-11-07T19:06:13.627 に答える
1

これまでのところ、2つの選択肢があるようです。

  1. 全体をゼロで上書きします。(あなたの解決策)

  2. 変更されたすべての要素を記録し、それらの要素のみをリセットします。record[0].x = 3; record[0].y = 5;など。ただし、レコードを1回ループする必要があります。さらに説明すると、配列内の要素が値に設定されるたびに、その要素の配列内での配置を記録する必要があることを意味します。次に、ループを使用して、各要素にアクセスし、それを0に設定できます。したがって、スパース配列がある場合は、より効率的です。

実装によっては、なぜ#1ではなく#2が必要なのかがわかります...しかし、アルゴリズムの分析について心配する必要がある十分な大きさのマトリックスが真剣にある場合は、ある種のサーバーを事前に実行することを検討してください。処理。

于 2012-11-07T18:41:17.703 に答える
0

問題を調べる別の別の方法は、線形配列を使用し、更新を行うときにx、yインデックスから線形インデックスを計算することです。

forその場合、初期化は時間O(x + y)の単一ループになります。

于 2012-11-07T18:50:09.907 に答える
-1

すべての要素に同じ値を割り当てる最も速い方法は、Array.map()を呼び出すことです。

しかし、ここには落とし穴があります。これにより、そのメソッドをネイティブに実装したブラウザーで非常に高速なパフォーマンスが得られ、他のブラウザーでは通常のパフォーマンスが得られることに注意してください。また、一部の古いブラウザでは.map()を使用できないため、Underscore.jsまたはそのメソッドを提供するその他のライブラリを使用する必要があることにも注意してください。

于 2012-11-07T18:38:20.953 に答える