1

So according to this discussion there is no constant time method for getting the size of a Dictionary object.

I'm trying to implement a wrapper which adds this functionality. Nothing fancy - just a 'numPairs' property and overridden methods to keep it updated. The problem lies in that the [] operator is used to add key/value pairs, rather than a named method, so I don't know how to override this to keep my counter updated. I could just do something like...

public function addPair(key:*, val:*):void {
    this[key] = val;
    numPairs++;
}

...but it'd be really nice if I could keep the bracket notation. Does anyone know of a solution?

Community
  • 1
  • 1
samlan
  • 45
  • 5
  • Just curious, why is the length important? Why aren't you using an Array or Vector in the case? – Mark Knol Sep 14 '12 at 21:46
  • I'm using this to store items on a game board, and I need to be able to quickly access them based on keys (locations on a square grid), as well as know the number of items I have on the board for various other things. – samlan Sep 15 '12 at 00:01

2 Answers2

2

If you want to keep the bracket notation you can still use the Proxy class for that, wrapping a real dictionary. Here an implementation using the Proxy class, but here i didn't use a weak dictionary because it can be tricky as the 'key' can be garbaged collected and you will not be aware of that. Of course performance operation (adding, removing, ...) will also be lower than the real dictionary.

here the live test : http://wonderfl.net/c/dstz

import flash.utils.Dictionary;
import flash.utils.Proxy;
import flash.utils.flash_proxy;

public class MyDict extends Proxy {
    private var _size:int = 0;
    private var _dict:Dictionary = new Dictionary();

    public function get size():int {
        return _size;
    }

    flash_proxy override function getProperty(name:*):* {
        return _dict[name];
    }

    flash_proxy override function setProperty(name:*, value:*):void {
        if (!_dict.hasOwnProperty(name))
            _size ++;
        _dict[name] = value;
    }

    flash_proxy override function deleteProperty(name:*):Boolean {
        if (_dict.hasOwnProperty(name)) {
            _size --;
            delete _dict[name];
            return true;
        }
        return false;
    }
}

var dict:MyDict = new MyDict();
dict[1] = 2;
dict["foo"] = "bar";
trace(dict.size, dict[1], dict["foo"]);

delete dict[1];
trace(dict.size, dict[1], dict["foo"]);
Patrick
  • 15,702
  • 1
  • 39
  • 39
  • Thanks! This is exactly what I was looking for. I'm curious as to why you mentioned the performance difference - were you referring to the extra operation of incrementing _size, and the extra function call through the wrapper? Or is there something I'm missing? – samlan Sep 14 '12 at 23:59
  • @Patrick "Of course performance operation (adding, removing, ...) will also be lower than the real dictionary." By how much? I'm thinking about doing something similar to my Dictionary subclass, which is constantly being told to figure out what its keys are at whatever particular moment and return them in a function call. Would it be faster if I did something like this, except maintaining instead the collection of keys to not have to iterate through each time, not just the count? – Panzercrisis Mar 14 '13 at 14:05
  • Your implementation will save the keys only as Strings or QName objects. It is not possible to write a dictionary with strict equal check. In your example `dict[0]` will result in a key "0". Means dict[0] == dict["0"] – Larusso Jan 20 '14 at 15:22
1

I understand you like that you want to keep actual pair count, and you should also check for undefined/null value passed that would indicate a removal of pair. So, you first check if there is a key in "this", then assign value.

public function addPair(key:String, val:*):void {
    if (this[key]) {
        // pair exists, updating
        this[key]=val;
        if (!val) numPairs--;
    } else {
        // pair does not exist, adding
        if (val) {
            this[key]=val;
            numPairs++;
        }
    }
}
Vesper
  • 18,599
  • 6
  • 39
  • 61