Obtener el tamaño del diccionario ActionScript 3


var d:Dictionary = new Dictionary();
d["a"] = "b";
d["b"] = "z";

Cómo obtener la longitud/tamaño del diccionario (que es 2) ?

Author: Bart van Heukelom, 2010-03-05

3 answers

No hay un método incorporado para obtener el tamaño/longitud/conteo de un diccionario AS3. Hay soluciones alternativas: por ejemplo, puede crear una clase de diccionario personalizada que extienda o envuelva la clase flash.utils.Dictionary, agregando la funcionalidad de contador. Puede administrar el conteo a medida que se agregan/eliminan las entradas, o contar bajo demanda usando una iteración de bucle For simple:

public static function countKeys(myDictionary:flash.utils.Dictionary):int 
{
    var n:int = 0;
    for (var key:* in myDictionary) {
        n++;
    }
    return n;
}
 32
Author: M.A. Hanin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-05 13:06:55

Lo ideal sería simplemente implementar un contenedor alrededor del Diccionario que extiende la clase Proxy. Eso le permite anular e interceptar la adición y eliminación de propiedades del Diccionario, permitiendo que la nueva clase del Diccionario se use exactamente como la original, con la misma sintaxis y habilidades exactas, con la adición de una función de longitud que devuelve el número de claves.

Esta implementación funciona de la siguiente manera. Cuando se establece o elimina una propiedad, comprueba si la propiedad ya existe (si es estrictamente igual a undefined) y aumenta o disminuye el contador de longitud interna en consecuencia. Esta implementación también elimina automáticamente una entrada cuando su valor se establece en undefined por coherencia.

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

NO USE ESTA IMPLEMENTACIÓN; USE LA QUE LE SIGUE EN SU 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;
        }
    }
}

DESCARGO DE RESPONSABILIDAD: La implementación anterior, aunque el enfoque más prometedor que podría haber funcionado en teoría, es en última instancia un callejón sin salida, ya que el Diccionario es inherentemente incompatible con los métodos de interfaz Proxy.

Primero, el setProperty, getProperty, y deleteProperty los métodos parecen recibir parámetros name sin tipo, pero son en realidad, los objetos QName fuertemente tipeados, que esencialmente restringen sus claves a String nombres de tipo, al igual que Object y asocian matrices. Dictionary no está limitado por esta limitación y permite usar instancias de objetos como claves únicas, por lo que es inherentemente incompatible con los métodos de la 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 nextName de Proxy le impide enumerar sobre todas las claves Dictionary por la misma razón, porque tiene un valor de retorno de tipo fuerte de String. Así que incluso si setProperty, getProperty en realidad aceptó claves sin escribir para los nombres, todavía no sería capaz de recuperarlos a través de la enumeración porque el método nextName devuelve solo cadena de tipo. Dictionary está simplemente en una clase propia.

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

Dado todo lo anterior, una mejor implementación sería la siguiente, donde se manipula el diccionario llamando a métodos como getValue / setValue / removeValue, y se tiene acceso a una enumeración de claves, así como a una propiedad 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
Author: Triynko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-05 06:44:24

Puedes usar DictionaryUtil:

var dictionaryLength : int = DictionaryUtil.getKeys(d).length;
 0
Author: MichelAngelo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-07 15:12:32