2010-03-05 44 views

回答

32

没有内置方法来获取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; 
} 
+1

太糟糕了,必须建立一个包装。 – 2010-03-05 15:07:52

+47

我应该在哪里使用Adobe来做这件事? – 2011-04-19 14:57:52

+1

有必要避免For循环中的陷阱,即当用for..in循环数组时会发生什么。 – Brilliand 2011-10-16 20:48:59

0

一个理想的情况只是实现围绕字典的包装,它扩展了Proxy类。这允许您重写和拦截Dictionary中的属性的添加和删除,从而允许新的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; 
     } 
    } 
} 

免责声明:以上的实施,虽然在理论上可以工作过的最有前途的方法,最终是死路一条,因为字典是与代理接口的方法本质上是不相容。

首先,setPropertygetPropertydeleteProperty方法似乎收到非类型参数name,实际上却是强类型QName对象,基本上限制你的钥匙String类型名,就像Object和准阵列。 Dictionary不受此限制的束缚,并允许将对象实例用作唯一键,所以它本质上与Proxy类方法不兼容。 Dictionary类的文档也有一个注释,它明确指出QName对象不能用作键。

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

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

鉴于上述所有的,更好的实现将是如下,你操纵,其中通过调用方法如的getValue/setValue方法/ removeValue字典,并有机会获得一个键枚举以及length属性:

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; 
    } 
0

您可以使用DictionaryUtil:

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