2012-12-07 4 views
29

可能性の重複:これはまた、私はいくつかを見つけた「ディープコピー」と呼ばれ、
What is the most efficient way to clone a JavaScript object?は多次元配列のコピーを作成し、参照しない - JavaScriptを

上の記事一番近いのはthis oneと思われますが、これはjQuery用です - ライブラリなしでこれを実行しようとしています。

私もそれは同じような何かを行うことが可能だということを、2つの場所で、見てきました:

arr2 = JSON.decode(JSON.encode(arr1)); 

しかし、それは明らかに非効率的です。また、各値を個別にループしてコピーし、すべての配列を繰り返すこともできます。それは疲れて、非効率的でもあるようです。

JavaScriptの多次元配列をコピーする最も効率的でライブラリ以外の方法は何ですか?[[a],[b],[c]]?私は、必要であれば "非IE"メソッドに完全に満足しています。

ありがとうございます!

+0

あなたは効率がどれくらい必要ですか?クライアントでこれを何度も何度もやっていますか(またはNodeのようなこのサーバー側ですか)? JSON stringify - > parseメソッドは、最も効率的ではないにしても非常に滑らかです。 –

+0

それ以外の場合、ディープコピーとは再帰的ループを意味します。 –

+0

構造体にはどのような種類のデータが保持されますか?それだけで配列、または他のオブジェクトですか?あなたの構造がどれくらい深いかが分かっていますか? –

答えて

38

配列の配列を未知のレベルまで扱っているように思えますが、いつでもある深さでそれらを処理する必要があるだけで、シンプルで速くなります.slice()を使用してください。

var newArray = []; 

for (var i = 0; i < currentArray.length; i++) 
    newArray[i] = currentArray[i].slice(); 

またはその代わりforループの.map()を使用して:

var newArray = currentArray.map(function(arr) { 
    return arr.slice(); 
}); 

だから、これは現在の配列を反復して、ネストされた配列の浅いコピーの新しい配列を作成します。そして、次の深さに進むと、同じことをします。

もちろん、配列と他のデータが混在している場合は、スライスする前に何をテストしたいでしょう。

+0

私は、余分な関数呼び出しを持つマップは、ほとんどのブラウザではるかに遅いと思いますが、インライン展開で最適化してより良い結果を得られるかもしれません。 – Bergi

+0

@Bergi:ええ、地図のバージョンはちょっとしたヒットになりますが、いいですし清潔です。 –

+0

うわー、地図は本当にきれいです –

5

私は確信してどのくらい良くJSON.stringyJSON.parseencodedecodeよりもないんだけど、あなたは試みることができる:私が見つけた他の

JSON.parse(JSON.stringify(array)); 

は何か(私はそれを少し変更したいが):

http://www.xenoveritas.org/blog/xeno/the-correct-way-to-clone-javascript-arrays

function deepCopy(obj) { 
    if (typeof obj == 'object') { 
    if (isArray(obj)) { 
     var l = obj.length; 
     var r = new Array(l); 
     for (var i = 0; i < l; i++) { 
     r[i] = deepCopy(obj[i]); 
     } 
     return r; 
    } else { 
     var r = {}; 
     r.prototype = obj.prototype; 
     for (var k in obj) { 
     r[k] = deepCopy(obj[k]); 
     } 
     return r; 
    } 
    } 
    return obj; 
} 
+0

これらの両方の欠点JSONのバージョンが何をするのかはわかりませんが、2番目の例は無限にループします) – Jeff

+0

@Jeff私はあなたを信頼しますが、あなたは(小さな)例を挙げますか?ちょうど理解したかった – Ian

+0

'var x = {}; 'deepCopy'が呼び出されるたびに' else'文にヒットし、JSONだけでは自己参照を扱うことができません - それは本来ツリーベースです – Jeff

3

二度同じノードを訪問していない任意の再帰アルゴリズムは約になります(ブラウザでは少なくとも)javascriptと同じくらい効率的です - 他の言語の特定の状況では、メモリの塊をコピーすることで逃げるかもしれませんが、JavaScriptは明らかにその能力を持っていません。

already done itというユーザーを探して、その実装を使用して正しいことを確認することをお勧めします。一度だけ定義する必要があります。

4

パフォーマンスを求めるときは、非ジェネリックソリューションにもなると思います。既知数のレベルを持つ多次元配列をコピーするには、最も簡単な解決策、いくつかのネストされたforループを使用する必要があります。あなたの二dimensioanl配列の場合、それは単に次のようになります。

var len = arr.length, 
    copy = new Array(len); // boost in Safari 
for (var i=0; i<len; ++i) 
    copy[i] = arr[i].slice(0); 

ネイティブslice methodは、forループのカスタムよりも効率的である、まだそれは深いコピーを作成しませんので、我々だけでそれを使用することができます最低レベル。

関連する問題