Actionscript3でベクターを配列に変換する最も良い方法は何ですか?
通常のキャスト構文は機能しません。
var myVector:Vector.<Foo> = new Vector();
var myArray:Array = Array(myVector); // calls the top-level function Array()
array関数が存在するためです。上記の結果は配列になりますが、これは元のVectorで構成される単一の要素を持つ配列です。
これにより、少し冗長になります。
var myArray:Array = new Array();
for each (var elem:Foo in myVector) {
myArray.Push(elem);
}
少し言葉遣いはありますが、これで問題ないと思います。これはそれを行うための標準的な方法ですか、それとも標準ライブラリのどこかに隠れているtoArray()関数がありますか?
あなたのアプローチは最速です...あなたがそれが冗長であると思うなら、それから効用関数を構築してください... :)
編集:
ユーティリティ関数を作成するには、おそらく次のように型を削除する必要があります。
function toArray(iterable:*):Array {
var ret:Array = [];
for each (var elem:Foo in iterable) ret.Push(elem);
return ret;
}
VectorとArrayの両方に使用できるforEachという関数があります。基本的には、ベクトル内の各要素の関数を呼び出します。これがその仕組みです:
var myVector:Vector.<Foo> = new Vector();
var myArray:Array = [];
myVector.forEach(arrayConverter);
function arrayConverter(element:*, index:int, array:Array):void{
myArray[myArray.length] = element;
}
しかし、すべての値をベクトルから配列に移動するだけの関数は見つかりませんでした。別の解決策は、Vectorクラスを拡張するクラスを作成し、toArray()というパブリック関数を作成し、その関数にそのコードを含めることで、変換するたびにコードを記述する必要がないようにすることです。
編集:今日この古い質問を見つけ、この日曜日の朝にすべての異なる方法のベンチマークテストを行うのは興味深いだろうと思いました。
1000000アイテムのベクトルを使用し、ループごとに2つのテストを行いました。 1つは組み込みの配列関数Pushを使用し、もう1つは通常の配列操作を使用します。
そして、これが1000アイテムを使用したベンチマークです。
基本的には、10000を超えるアイテムを取得すると、本当の違いがわかり始めます。したがって、0から10000のアイテムの間では、どちらを使用するかは実際には重要ではありません。
package
{
public class Loops{
public static function forLoop(vector:Vector.<Foo>, usePush:Boolean = false):Array{
var result:Array = [];
for(var i:int = 0; i < vector.length; i++){
if(usePush){
result.Push(vector[i]);
}else{
result[result.length] = vector[i];
}
}
return result;
}
public static function foreachLoop(vector:Vector.<Foo>, usePush:Boolean):Array{
var result:Array = [];
for each(var key:String in vector){
if(usePush){
result.Push(vector[key]);
}else{
result[result.length] = vector[key];
}
}
return result;
}
public static function whileLoop(vector:Vector.<Foo>, usePush:Boolean):Array{
var result:Array = [];
var i:int = 0;
while(i < vector.length){
if(usePush){
result.Push(vector[i]);
}else{
result[result.length] = vector[i];
}
}
return result;
}
public static function arrayUtilLoop(vector:Vector.<Foo>, usePush:Boolean):Array{
var result:Array = [];
function arrayUtilForeach(element:*, index:int, array:Array):void{
if(usePush){
array.Push(element);
}else{
array[result.length] = element;
}
}
vector.forEach(arrayUtilForeach);
return result;
}
}
}
GetTimer関数を使用してベンチマークを実行したため、100%正確ではない可能性がありますが、ループごとに大きな違いがあるため、問題ではないと思います。
誰かがこれがお役に立てば幸いです。
使用する:
var myArray:Array = [];
myArray.Push.apply(null, myVector);
または
var myArray:Array = new Array().concat(myVector);
Vaukalakの2番目の回答は機能するだけでなく、ここで投票された上位の回答よりもはるかに高速です。[]は新しいArray()よりもわずかに高速な配列構築を生成するため、少しマッサージしました。また、配列からベクターを作成するための最良の方法も以下に含まれています。
// make a Vector from an array
var toVector : Vector.<String> = Vector.<String>(['a','b','c'])
// populate an array from a Vector
var toArray : Array = [].concat(toVector);
これはフラッシュ11でのみ機能するようです
それぞれについて、あなたのアイテムの順序が同じになることを保証するものではありません。
for inは、より近い一致を与えるはずです。
private var _vector:*;
public function VectorUtil(vector:*)
{
_vector = vector;
}
public function toArray():Array
{
var a:Array = [];
for (var i:int = 0; i < _vector.length; ++i)
a.Push(_vector[i]);
return a;
}
ベクター内の各要素の関数呼び出しは、特に長いベクターでは、かなり遅くなります。ただし、かなり長いVector/Arrayを扱っている場合を除いて、これらの例はおそらくすべて同等です。一般に、最適化よりも読みやすさと使いやすさが重要です。
そうは言っても、最も速い方法は、0と比較してイテレータでwhileループを使用することだと思います。
var myArray:Array = new Array(myVector.length);
var i:int=myVector.length;
while (i--) {
myArray[i] = myVector[i];
}
残念ながら、一般的な基本型のVectorメソッドパラメータを指定する方法がないため、繰り返し使用しやすいようにこの手法をメソッドに詰め込むことはできません。..:(