2010-03-05 11 views

Respuesta

32

No hay ningún método integrado para obtener el tamaño/longitud/recuento de un diccionario AS3. Existen soluciones: por ejemplo, puede crear una clase de diccionario personalizada que amplíe o envuelva la clase flash.utils.Dictionary, agregando la funcionalidad del contador. Puede administrar el recuento medida que se añaden/eliminan las entradas, o contar la carta utilizando un simple bucle For iteración:

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

Lástima, tuvo que construir un envoltorio. –

+47

¿A dónde voy para votar a Adobe por hacer esto? –

+1

Era necesario evitar los errores en los bucles For, es decir, lo que sucede cuando se realiza un bucle sobre una matriz con for..in. – Brilliand

0

lo ideal sería simplemente aplicar una envoltura alrededor de diccionario que se extiende la clase Proxy. Esto le permite anular e interceptar la adición y eliminación de propiedades del Diccionario, permitiendo que la nueva clase de Diccionario se use exactamente igual que el original, con la misma sintaxis y habilidades, con la adición de una función de longitud que devuelve el número de llaves.

Esta aplicación funciona de la siguiente manera. Cuando se establece o borra una propiedad, se verifica si la propiedad ya existe (si es estrictamente igual a indefinida) y se incrementa o disminuye el contador interno de la longitud en consecuencia. Esta implementación también elimina automáticamente una entrada cuando su valor se establece en indefinido para la coherencia.

escribí este Diccionario envoltorio sólo para esta pregunta; tomó aproximadamente 5 minutos, y proporciona una función de longitud que devuelve la longitud. Elegí hacerlo una función en lugar de una propiedad para que no interfiera con los nombres de propiedad o la enumeración de las propiedades del diccionario.

NO utilizar esta implementación; UTILIZA EL QUE LO SIGUE EN LUGAR. Explico por qué a continuación.

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

AVISO: La implementación anterior, aunque el enfoque más prometedor que podría haber trabajado en la teoría, en última instancia, es un callejón sin salida, ya diccionario es inherentemente incompatibles con los métodos de la interfaz de proxy.

primer lugar, el setProperty, getProperty y deleteProperty métodos parecen recibir sin tipo name parámetros, pero en realidad son fuertemente tipado QName objetos, que restringen esencialmente las llaves a String nombres de tipo, al igual que Object y matrices asociadas. Dictionary no está sujeto a esta limitación y permite usar instancias de objeto como claves únicas, por lo que es inherentemente incompatible con los métodos de clase Proxy. La documentación de la clase Dictionary también tiene una sola nota, y establece explícitamente que los objetos QName no se pueden usar como claves.

Del mismo modo, el método de proxy nextName le impide enumerar sobre todas las teclas Dictionary por la misma razón, ya que tiene un valor de retorno de tipo fuerte de String. Así que incluso si setProperty, getProperty teclas sin tipo realmente aceptados para los nombres, todavía no sería capaz de recuperarlos a través de la enumeración ya que el método devuelve sólo nextName tipo cadena. Dictionary es simplemente una clase propia.

Lo mejor que podría hacer es implementar un contenedor como el anterior que expone el diccionario subyacente para la enumeración, pero otros requieren llamar métodos addKey/removeKey explícitos con nombres y valores sin tipo, en lugar de usar el comportamiento del Proxy.

Teniendo en cuenta todo lo anterior, una mejor aplicación sería de la siguiente manera, donde manipular el diccionario llamando a métodos como getValue/setValue/removeValue, y tener acceso a una enumeración de claves, así como una propiedad de longitud:

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

puede utilizar DictionaryUtil:

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