Note that there are two aspects to the technical solution: equality comparison and indexing .
Cliff Notes Version:
- Easy to do regular equality comparison
- To perform indexing , you need to know more than one object is equal to another - you need to know which object is larger than the other.
- If all of your properties are primitives, you must put them on the same line and use
Object to track them (NOT a Dictionary ). - If you need to compare some individual properties for referential equality, you will have a write function to determine which set of properties is greater than the other, and then create your own collection class that uses the output comparison function to implement your own indexing based on binary search.
- If the number of unique sets of arguments is a few hundred or less and you need a link comparison for your
Object argument, just use the Array method and some to naively compare with all cached keys, Only you know how expensive your actual method is, so you decide how much The search (which depends on the number of unique arguments provided to the function) is acceptable.
Equality comparison
To address equality comparisons , itโs simple enough to write code to compare objects for their property values, and not for reference equality. The following function provides a strict comparison, so that both objects must contain exactly the same properties (without additional properties for any permitted object) with the same values:
public static propsEqual(obj1:Object, obj2:Object):Boolean { for(key1:* in obj1) { if(obj2[key1] === undefined) return false; if(obj2[key1] != obj2[key1]) return false; } for(key2:* in obj2) if(obj1[key2] === undefined) return false; return true; }
You can speed it up by eliminating the second cycle with a compromise that {A:1, B:2} will be considered equal to {A:1, B:2, C:'An extra property'} .
Indexing
The problem with this in your case is that you lose indexing , that Dictionary provides referential equality, or that Object provides string keys. You will need to compare each new set of function arguments with the entire list of previously seen arguments, for example using Array.some . I use the currentArgs field and the method to avoid generating a new close every time.
private var cachedArgs:Array = []; private var currentArgs:Object; function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* { currentArgs = { stringArg:stringArg, objArg:objArg, boolArg:boolArg }; var iveSeenThisBefore:Boolean = cachedArgs.some(compareToCurrent); if(!iveSeenThisBefore) cachedArgs.push(currentArgs); } function compareToCurrent(obj:Object):Boolean { return someUtil.propsEqual(obj, currentArgs); }
This means that the comparison will be O (n) time, where n is an increasing number of unique sets of function arguments.
If all the arguments to your function are primitive, see a very similar question In AS3, where do you draw a line between the Dictionary and the ArrayCollection? . The name does not seem very similar, but the solution in the accepted answer (yes, I wrote it) concerns the same technical problem - using several primitive values โโas one composite key. The main point in your case:
private var cachedArgs:Object = {}; function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* { var argKey:String = stringArg + objArg.toString() + (boolArg ? 'T' : 'F'); if(cachedArgs[argKey] === undefined) cachedArgs[argKey] = _yourMethod(stringArg, objArg, boolArg); return cachedArgs[argKey]; } private function _yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
If you really need to determine which link is โbiggerโ than the other (as Dictionary does internally), you will have to sneak into some ugly things since Adobe has not yet provided an API to extract the link โvalueโ / โaddressโ. The best I have found so far is an interesting hack: How can I get an "instance memory location"? in ActionScript? . Without performing a bunch of performance tests, I donโt know if using this hack to compare links will kill the benefits gained by the indexnig binary search tree. Naturally, this will depend on the number of keys.