【问题标题】:Get size of ActionScript 3 Dictionary获取 ActionScript 3 字典的大小
【发布时间】:2011-01-24 02:43:11
【问题描述】:
var d:Dictionary = new Dictionary();
d["a"] = "b";
d["b"] = "z";

如何获取字典的长度/大小(为2)?

【问题讨论】:

    标签: flash actionscript-3 actionscript dictionary hashtable


    【解决方案1】:

    没有内置方法可以获取 AS3 字典的大小/长度/计数。 有一些解决方法:例如,您可以创建一个自定义字典类,它扩展或包装flash.utils.Dictionary 类,添加计数器功能。您可以在添加/删除条目时管理计数,或者使用简单的 For 循环迭代按需计数:

    public static function countKeys(myDictionary:flash.utils.Dictionary):int 
    {
        var n:int = 0;
        for (var key:* in myDictionary) {
            n++;
        }
        return n;
    }
    

    【讨论】:

    • 太糟糕了,不得不构建一个包装器。
    • 有必要避免 For 循环中的陷阱,即使用 for..in 循环遍历数组时会发生什么。
    • 仍然可以提供一个内置的 DictionaryUtils 类。
    【解决方案2】:

    理想情况下,只需在 Dictionary 周围实现一个包装器,该包装器扩展了 Proxy 类。这允许您覆盖和拦截 Dictionary 中属性的添加和删除,允许使用新的 Dictionary 类与原始类完全一样,具有完全相同的语法和能力,并添加一个返回数量的长度函数键。

    此实现的工作原理如下。当设置或删除一个属性时,它会检查该属性是否已经存在(是否严格等于未定义)并相应地增加或减少内部长度计数器。当条目的值设置为 undefined 以保持一致性时,此实现还会自动删除条目。

    我为这个问题编写了这个 Dictionary 包装器;大约花了 5 分钟,它提供了一个返回长度的长度函数。我选择使它成为一个函数而不是一个属性,这样它就不会干扰属性名称或字典属性的枚举。

    请勿使用此实现;改用跟随它的那个。我在下面解释原因。

    package flos.utils 
    {
        import flash.utils.flash_proxy;
        import flash.utils.Proxy;
    
        public class Dictionary extends Proxy
        {
            private var d:flash.utils.Dictionary;
            private var _length:int = 0;
    
            public function Dictionary( weakKeys:Boolean = false ) 
            {
                d = new flash.utils.Dictionary( weakKeys );
            }
    
            public function length():int
            {
                return _length;
            }
    
            override flash_proxy function getProperty(name:*):* 
            {
                return d[name];
            }
    
            override flash_proxy function setProperty(name:*, value:*):void 
            {
                if (value === undefined) //delete property when explicitly set to undefined, to enforce rule that an undefined property does not exist and is not counted
                {
                    delete this[name];
                    return;
                }
                if (d[name] === undefined)
                    _length++;
                d[name] = value;
            }
    
            override flash_proxy function deleteProperty(name:*):Boolean 
            {
                if (d[name] !== undefined)
                {
                    delete d[name];
                    _length--;
                    return true;
                }
                return false;
            }
        }
    }
    

    免责声明:上面的实现虽然是理论上可行的最有希望的方法,但最终是死路一条,因为 Dictionary 本质上与 Pr​​oxy 接口方法不兼容。

    首先,setPropertygetPropertydeleteProperty 方法似乎接收无类型的 name 参数,但它们实际上是强类型的 QName 对象,这实际上将您的键限制为 String 类型名称,就像Object 和关联数组一样。 Dictionary 不受此限制的约束,允许使用对象实例作为唯一键,因此它与 Proxy 类方法本质上是不兼容的。 Dictionary 类的文档也有一个注释,它明确指出 QName 对象不能用作键。

    同样,Proxy 的nextName 方法会阻止您枚举所有Dictionary 键,原因相同,因为它具有强类型返回值String。因此,即使setPropertygetProperty 实际上接受了名称的无类型键,您仍然无法通过枚举检索它们,因为nextName 方法仅返回类型字符串。 Dictionary 只是属于它自己的一个类。

    您可以做的最好的事情是实现一个像上面这样的包装器,它公开底层字典以进行枚举,但其他人需要使用非类型化名称和值调用显式 addKey/removeKey 方法,而不是使用代理行为。

    鉴于以上所有情况,更好的实现如下,您可以通过调用 getValue/setValue/removeValue 等方法来操作字典,并可以访问键枚举和长度属性:

    public class Dictionary
    {
        private var d:flash.utils.Dictionary;
        private var _keys:Array;
    
        public function Dictionary( weakKeys:Boolean = false )
        {
            d = new flash.utils.Dictionary( weakKeys );
            _keys = new Array();
        }
    
        public function get keys():Array
        {
            return _keys.concat(); //return copy of keys array
        }
    
        public function get length():int
        {
            return _keys.length;
        }
    
        public function containsKey( key:* ):Boolean
        {
            return d[key] !== undefined;
        }
    
        public function setValue( key:*, value:* ):void
        {
            if (value === undefined) //delete property when explicitly set to undefined, to enforce rule that an undefined property does not exist and is not counted
            {
                removeValue( key );
                return;
            }
            if (d[key] === undefined)
            {
                _keys.push( key );
            }
            d[key] = value;
        }
    
        public function getValue( key:* ):*
        {
            return d[key];
        }
    
        public function removeValue( key:* ):Boolean
        {
            if (d[key] !== undefined)
            {
                delete d[key];
                var i:int = _keys.indexOf( key );
                if (i > -1)
                    _keys.splice( i, 1 );
                return true;
            }
            return false;
        }
    

    【讨论】:

      【解决方案3】:

      您可以使用 DictionaryUtil:

      var dictionaryLength : int = DictionaryUtil.getKeys(d).length;
      

      【讨论】:

        猜你喜欢
        • 2011-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-10
        相关资源
        最近更新 更多