Monday, December 13, 2010

How to make Associative Array using Proxy

Many times you need to access elements thru index as key but sometime thru object or string as key. Here comes Associative Array.
Simplest way of making Associative Array is by using normal Array.

var arr:Array=new Array();
arr['mile']=111;
arr[0]=222;
//you cant var myObject:Object={}; arr[myObject]=333;

If I do

trace(arr.join(','));

would return 222. But where is my element at 'mile' ?;
Above implementation is very slow and have restriction of using objects as keys, join, reverse, slice, splice and other useful function don't work properly.
Even in ActionScript documents you will find recommendation of use of Object for Associative Arrays.

Lot of problems would be solved if we have internal indexer structure.
We could build something like:

var arrThruKeys:Array=new Array();
var arrThruIndex:Array=new Array();
var myElement:int=222;
arrThruKeys['mile']=myElement;
arrThruIndex[0]=myElement;

or as documentation propose:

var objThruKeys:Object=new Object();
var arrThruIndex:Array=new Array();
var myElement:int=222;
objThruKeys['mile']=myElement;
arrThruIndex[0]=myElement;


If we want all Array functions to function same and we could access elements thru key or thru index, we need to use something like this

public class AssociativeArray
{
var objThruKeys:Object=new Object();
var arrThruIndex:Array=new Array();

public function push(key:*,value:*):void
{
var elem:Object={key:key,value:value,inx:arrThruIndex.length};
objThruKeys.key=elem
arrThruIndex[arrThruIndex.length]=elem
}

public function getByKey(key:*):*
{
return objThruKeys[key].value;
}

public function getByInx(key:*):*
{
return arrThruIndex[key].value;
}

public function reverse():void
{
arrThruIndex.reverse();
}


}


How we could keep direct speed access thru index that array offer and avoid slow slow operations like unshift, splice (remove,insert), merge ... etc. I decided to use Single Linked List and for direct access I prefer using Dictionary ( until utilizing HashTable to this implementation for more speed) . Instead of using dynamic object {key:key,value:value,inx:arrThruIndex.length} which is much slower then using object from final class

final class SNode
{
public var key:*;
public var value:*;
public var inx:int;

public function SNode(key:*,value:*,inx:int):void
{
this.key=key;
this.value=value;
this.inx=inx;
}

}


In order we use [] operator instead of getByIndex and getByKey functions, also to use for each and for..in in normal way and easy to replace some older code with just replacing Array with AssociativeArray/AssociativeFastArray,
we could extended our class from dynamic Proxy Class.(maybe little bit slower but clean and fast development).


var assoc:AssociativeFastArray=new AssociativeFastArray();

//this is tha same as assoc.first='first';
assoc['first']='firstvalue';
assoc[0]='new first value';//element at inx 0 will be overwritten in strict mode


NEXT:
- reverse function to be implemented
- sort functions to be implemented
- strict mode test
- bug testing and optimization


Download

No comments:

Post a Comment