AS3: How to convert a Vector to an Array
Asked Answered
A

8

23

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?

Azalea answered 10/7, 2009 at 5:12 Comment(2)
for(var i:int; i < muVector.length; ++i){} may be faster. But there is no other solution.Amain
Also, using myArray[myArray.length] = elem; is faster than using push().Puga
B
24

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;
}
Branchia answered 10/7, 2009 at 8:12 Comment(1)
Building a utility function isn't an option since it couldn't apply to any type of Vector... unless anyone knows of a way to make a function that takes as a parameter ANY type of Vector?Anacardiaceous
P
20

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.

Vector documentation

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.

  • For loop, not push: 520 ms
  • For loop, push: 1027 ms
  • Foreach loop, not push: 1753 ms
  • Foreach loop, push: 2264 ms
  • While loop, not push: 2775 ms
  • While loop, not push: 3282 ms
  • Util loop, not push: 4059 ms
  • Util loop, push: 4570 ms

And here is a benchmark using 1000 items:

  • For loop, not push: 1 ms
  • For loop, push: 2 ms
  • Foreach loop, not push: 2 ms
  • Foreach loop, push: 3 ms
  • While loop, not push: 3 ms
  • While loop, not push: 4 ms
  • Util loop, not push: 4 ms
  • Util loop, push: 5 ms

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.

Puga answered 10/7, 2009 at 7:1 Comment(4)
very nice, but extremely slow ... you realize how many calls this makes?Branchia
yes, in my opinion it's nicer than using a for/for each loop. It's a function call for each element in the Vector. How much slower exactly is this approach?Puga
you don't want to call myVector.length in every loop. by removing it i've more than doubled the performance, pastebin.com/0waTqaER checking length each time = 491 not checking length each time = 209Lupita
Just a note: for each does not guarantee any particular order: #619466 Although it may be that the as3 implementation does actually behave as desired.Skylight
S
6

use:

var myArray:Array = [];
myArray.push.apply(null, myVector);

or

var myArray:Array = new Array().concat(myVector);
Secular answered 13/3, 2012 at 9:41 Comment(1)
This constructs a one-element array with the vector as the first value...Dutchman
C
3

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;
    }
Ciaphus answered 7/11, 2011 at 3:41 Comment(0)
B
3

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

Baca answered 8/8, 2012 at 11:42 Comment(3)
This actually constructs a one-element array with the vector as the first value.Aurora
How does this wrong answer have so many votes? As jameshfisher points out, the behavior is incorrect. Is StackOverflow turning into a trolling site?Cuprum
@Jonathan, the answer to your first question is that this is a flash related question. The majority of the community are very junior developers.Clisthenes
E
0

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.... :(

Effector answered 11/9, 2009 at 1:7 Comment(0)
D
-4

If you have a vector of strings, you could do:

myArray = myVec.join(",").split(",");

for a quick and dirty Array conversion.

Dexter answered 21/6, 2010 at 18:32 Comment(2)
What if your strings have commas in them?Kampala
the splitter doesn't matter, so myVect.join(":|:").split(":|:") works just as well...Dexter
W
-13

var a:Array = some_vector as Array;

Waldemar answered 2/6, 2011 at 12:50 Comment(1)
A Vector cannot be casted as an Array. This code would return null.Wootten

© 2022 - 2024 — McMap. All rights reserved.