Reputation: 4268
What's the nicest way to convert a Vector to an Array in Actionscript3?
The normal casting syntax doesn't work:
var myVector:Vector.<Foo> = new Vector();
var myArray:Array = Array(myVector); // calls the top-level function Array()
due to the existance of the Array function. The above results in an array, but it's an array with a single element consisting of the original Vector.
Which leaves the slightly more verbose:
var myArray:Array = new Array();
for each (var elem:Foo in myVector) {
myArray.push(elem);
}
which is fine, I guess, though a bit wordy. Is this the canonical way to do it, or is there a toArray() function hiding somewhere in the standard library?
Upvotes: 23
Views: 28987
Reputation: 10268
There is a function called forEach which both Vector and Array has which you can use. Basically it calls a function for each element in the vector. This is how it works:
var myVector:Vector.<Foo> = new Vector();
var myArray:Array = [];
myVector.forEach(arrayConverter);
function arrayConverter(element:*, index:int, array:Array):void{
myArray[myArray.length] = element;
}
But I couldn't find a function which just moves all the values from the Vector to an Array. Another solution could be that you create a class which extends the Vector class and then you have a public function called toArray() and then you have that code in that function so you don't have to write it each time you want to convert.
Edit: Found this old question today and thought it would be interesting to do a benchmark test of all the different methods this sunday morning.
I used a vector with 1000000 items in and made 2 tests for each loop. One using the built in array functions push and one using regular array operations.
And here is a benchmark using 1000 items:
Basically it's when you get over 10 000 items you start to see the real difference. So between 0 and 10 000 items it doesn't really matter which you use.
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;
}
}
}
I used the getTimer function to do the benchmark, so it might not be 100% accurate but there's so much difference between the different loops so I don't think it matters.
I hope someone found this useful.
Upvotes: 20
Reputation: 95
Vaukalak second answer not only works but is much faster than the top voted answer here, I've massaged it a little as [] produces fractionally faster array construction than new Array(). Also included below is the best way to create a Vector from an Array too.
// 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);
Please note, this only seems to work with flash 11
Upvotes: 3
Reputation: 85
use:
var myArray:Array = [];
myArray.push.apply(null, myVector);
or
var myArray:Array = new Array().concat(myVector);
Upvotes: 6
Reputation: 61
for each will not guarantee that the order of your items will be the same.
for in should give you a closer match.
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;
}
Upvotes: 3
Reputation: 15623
your approach is the fastest ... if you think it's to verbose, then build a utility function ... :)
edit:
To build a utility function, you will probably have to drop the type as follows:
function toArray(iterable:*):Array {
var ret:Array = [];
for each (var elem:Foo in iterable) ret.push(elem);
return ret;
}
Upvotes: 24
Reputation: 9
If you have a vector of strings, you could do:
myArray = myVec.join(",").split(",");
for a quick and dirty Array conversion.
Upvotes: -4
Reputation:
a function call for each element in the Vector would be a LOT slower, particularly in a longer Vector. however, these examples are probably all equivalent, unless you're dealing with a fairly long Vector/Array -- legibility and ease of use are generally more important than optimization.
that said, i think the fastest way is to use a while loop with an iterator compared against 0.
var myArray:Array = new Array(myVector.length);
var i:int=myVector.length;
while (i--) {
myArray[i] = myVector[i];
}
unfortunately, you can't stuff this technique into a method for ease of repeated use, because there's no way to specify a Vector method parameter of a generic base type.... :(
Upvotes: 0