OK, my final conclusion:

<http://www.snafoo.org/tmp/flatten.swf>

Iterative *is* faster than recursion. Run the test and examine the
test class below. (Use an empty .fla, import it, call TestArray.main()
)

Also, we learn that whenever you have to get the item at the same
position of an array twice, store it in a local variable. Plus, and
this lead to significant improvements, don't use Array.push(), but
maintain the index in a local variable.

The fastest is the "new iterative", or "flatten4" as it is called in
the class below. We're talking 25% improvement over recursion. I've
changed the original one so it stores the index and parent on a stack
instead of a property so it can be used in Steven's Array class if he
likes.

It ain't pretty to look at, but it's pretty fast.

Mark



class TestArray extends Array {
        
        public static var testarray : Array;

        public static function main () : Void {
                var ta = TestArray.testarray = TestArray.randomArray( 100000 );
                var reference = ta.flatten().length;
                
                _root.createTextField( "tf", 1, 0, 0, 1024, 768 );
                _root.tf.text = "testing... will take a while, be patient.";
                
                var cntr = 0;
                var results = [ [], [], [], [] ];
                var labels = [ "recursive", "new recursive", "iterative", "new 
iterative" ];
                _root.onEnterFrame = function () {
                        if( cntr++ > 30 ) {
                                var n = (cntr % 4);
                                var res;
                                var start;
                                switch( n ) {
                                        case 0:
                                        start = getTimer();
                                        res = ta.flatten();
                                        break;
                                        
                                        case 1:
                                        start = getTimer();
                                        res = ta.flatten2();
                                        break;
                                        
                                        case 2:
                                        start = getTimer();
                                        res = ta.flatten3();
                                        break;

                                        case 3:
                                        start = getTimer();
                                        res = ta.flatten4();
                                        break;
                                }
                                
                                var dur = getTimer() - start;
                                
                                results[ n ].push( dur );
                                
                                if( res.length != reference ) {
                                        _root.tf.text += "\ncheck " + labels[ n ] + 
", gave result length
different from reference result.";
                                }
                                
                                _root.tf.text = res.length + ", " + labels[ n ] + ": 
" + dur;
                        }
                        if( cntr > 70 ) {
                                delete this.onEnterFrame;
                                
                                var totals = [];
                                
                                _root.tf.text = "The fastest results 
were...\n\n";
                                
                                for( var i in results ) {
                                        var result = results[ i ];
                                        var min = Number.MAX_VALUE;
                                        for( var k in result ) {
                                                min = Math.min( min, result[ k 
] );
                                        }
                                        
                                        _root.tf.text += "\nfor " + labels[ i ] + 
":\t" + min;
                                }
                        }
                        
                };
        }
                
        public static function randomArray(p) : Array {
               var a = new TestArray;
               for (var i = 0; i < p; i++) {
                       if (Math.random() * 2 < Math.random() * 5) {
                               a.push(i);
                       } else {
                               a.push(TestArray.randomArray(Math.ceil( 
Math.random() * 3 ) ));
                       }
               }
        
               _root.tf.text += "length: " + a.length;
        
               return a;
        }

        
        public function flatten (r) : Array {
               if (!r) r = [];
               var n = this.length;
               for (var a = 0; a < n; a++) {
                       if ( !(this[a] instanceof Array) ) {
                               r.push(this[a]);
                       } else {
                               this[a].flatten(r);
                       }
               }
        
               return r;
        };
        
        public function flatten2 (r) : Array {
               if (!r) r = [];
               var n = this.length;
               var foo;
               for (var a = 0; a < n; a++) {
                       if ( !((foo = this[a]) instanceof Array) ) {
                               r.push(foo);
                       } else {
                               foo.flatten2(r);
                       }
               }
        
               return r;
        };
        
        public function flatten3 () : Array {
                var outArray : Array = [];
                var list = this;
                list.index = 0;
                var item : Object;
                var index : Number;
                var length : Number;
                do {
                        index = list.index;
                        length = list.length;
                        while( index < length ) {
                                item = list[ index++ ];
                                if( item instanceof Array ) {
                                        item.parent = list;
                                        list.index = index;
                                        list = item;
                                        index = 0;
                                        length = list.length;
                                } else {
                                        outArray.push( item );
                                }
                        }
                } while( list = list.parent );
                
                return outArray;
        }

        public function flatten4 () : Array {
                var outArray : Array = [];
                var outIndex = 0;
                var list = this;
                list.index = 0;
                var item : Object;
                var index;
                var length : Number;
                var indices : Array = [ 0 ];
                var indicesIndex = 1;
                var lists : Array = [];
                var listsIndex = 0;
                do {
                        index = indices[ --indicesIndex ];
                        length = list.length;
                        while( index < length ) {
                                item = list[ index++ ];
                                if( item instanceof Array ) {
                                        lists[ listsIndex++ ] = list;
                                        indices[ indicesIndex++ ] = index;
                                        list = item;
                                        index = 0;
                                        length = list.length;
                                } else {
                                        outArray[ outIndex++ ] = item;
                                }
                        }
                } while( list = lists[ --listsIndex ] );
                
                return outArray;
        }

}

<<<
_______________________________________________
[email protected]
To change your subscription options or search the archive:
http://chattyfig.figleaf.com/mailman/listinfo/flashcoders

Brought to you by Fig Leaf Software
Premier Authorized Adobe Consulting and Training
http://www.figleaf.com
http://training.figleaf.com

Reply via email to