Actually, here it is:
package { import flash.display.Sprite; import flash.utils.ByteArray; /** * ... * @author wvxvw */ public class RemoveDuplicatesThroughByteArray extends Sprite { private var _patternA:ByteArray = new ByteArray(); private var _patternB:ByteArray = new ByteArray(); public function RemoveDuplicatesThroughByteArray() { super(); var result:Array = this.removeDuplicates( [ { foo:"123", bar:"345" }, { foo:"123", bar:"345", foobar:"789" }, { foo:"123", bar:"347" }, { foo:"123", bar:345 }, { bar:"345", foo:"123" } ]); this.dump(result); } private function dump(object:Object, depth:int = 0):void { var tabs:String = "\t\t\t\t\t\t\t\t\t\t".substr(0, depth - 10); for (var p:String in object) { trace(tabs, p, "=", object[p]); this.dump(object[p], depth + 1); } } private function removeDuplicates(array:Array):Array { this._patternB.clear(); this._patternB.length = 0; // If we write the whole thing ar once, the constants (such as strings // and numbers will be cached) // It looks like the properties are always written in the same // (reverse alphabetic) order. If you can prove this is wrong, // suppose the algorithm is not working! for each (var o:Object in array) this._patternB.writeObject(o); return array.filter(filterHelper); } private function filterHelper(object:Object, index:int, all:Array):Boolean { var bytes:ByteArray; var pos:int; var nextPos:int; var prevPos:int; var len:int = all.length; this._patternA.clear(); this._patternA.length = 0; this._patternA.writeObject(object); this._patternB.position = 0; while (pos <= index) { this._patternB.readObject(); pos++; } prevPos = this._patternB.position; main: while (pos < len) { this._patternB.position = prevPos; this._patternB.readObject(); nextPos = this._patternB.position; this._patternB.position = prevPos; this._patternA.position = 0; while (this._patternB.position < nextPos) { if (this._patternB.readUnsignedByte() !== this._patternA.readUnsignedByte()) { prevPos = nextPos; pos++; continue main; } } return false; } return true; } } }