配列コピー – ActionScript

ActionScriptで配列とかディープコピーするのはどんな方法が一般的なんだろうと思って調べてました。
今回は、僕のようなAS初級者向けの内容です。

以下のエントリーでByteArrayを使ってオブジェクトをディープコピーする例がありました。
ActionScriptでディープコピー
おぉ、けっこう簡単。後追いですが僕も検証してみました。

var list:Array = [0,1,2,3];

var ba:ByteArray = new ByteArray();  
ba.writeObject(list);  
ba.position = 0;  
var copy:Array = ba.readObject();  
  
trace(copy);
copy[2] = 4;
trace(copy);
trace(list);

//出力結果
0,1,2,3
0,1,4,3
0,1,2,3

うん、できてる。
次は100万個の要素をfor文でガリガリコピーしたものと速度比較。

var list:Array = new Array();
for(var i:int = 0; i < 1000000; i++) list.push(Math.random());
trace("List of "+list.length+" elements.");

//for
var ts1:Number = getTimer();
var copy1:Array = new Array();
for(var j:int = 0; j < list.length; j++) copy1.push( list[j] );
var te1:Number = getTimer();
trace("for(): "+(te1-ts1)+"ms");

//ByteArray
var ts2:Number = getTimer();
var ba:ByteArray = new ByteArray();  
ba.writeObject(list);
ba.position = 0;  
var copy2:Array = ba.readObject();  
var te2:Number = getTimer();  
trace("ByteArray: "+(te2-ts2)+"ms");

//出力結果
List of 1000000 elements.
for(): 363ms
ByteArray: 464ms

あれ。forの方が早い。ループ処理を最適化してさらに検証。

//最適化前
var ts1:Number = getTimer();
var copy1:Array = new Array();
for(var j:int = 0; j < list.length; j++) copy1.push(list[j]);
var te1:Number = getTimer();
trace("for(): "+(te1-ts1)+"ms");

//最適化後
var ts1:Number = getTimer();  
var copy1:Array = new Array();  
var len:int = list.length;  
for(var j:int = 0; j < len; j++) copy1[j] = list[j];
var te1:Number = getTimer();  
trace("for(): "+(te1-ts1)+"ms");  

//出力結果
List of 1000000 elements.
for(): 217ms
ByteArray: 468ms

ByteArrayで配列コピーすると遅いってことでいいのか。
ただ、100万個も要素コピーすることなんてまずないと思いますけど;
ここで、変数に配列名(copy1 = list)を代入すると配列のシャローコピー(浅いコピー)になりますが、
ループで要素を1つずつ入れてやれば(copy1[j] = list[j])ディープコピーができます。
C言語でも「配列名はアドレス」って大学生の時にしつこく教えられた記憶があります。

また、配列のコピーならArray.concat()、Array.slice()を使っても出来ます。

//slice()
var ts1:Number = getTimer();
var copy1:Array = list.slice(0, list.length);
var te1:Number = getTimer();
trace("slice(): "+(te1-ts1)+"ms");

//concat()
var ts2:Number = getTimer();
var copy2:Array = list.concat();
var te2:Number = getTimer();
trace("concat(): "+(te2-ts2)+"ms");

//出力結果
slice(): 46ms
concat(): 32ms

concat。速い。
なんか時間をムダにした気がする。。。。

あわせて読む:

2 Thoughts

  1. ピンバック: ArrayUtil (as3corelib) - Rest Term
  2. How i may contact the administrator of a site? I have a question.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です