Подтвердить что ты не робот

Получите размер словаря ActionScript 3

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

Как получить длину/размер словаря (который равен 2)?

4b9b3361

Ответ 1

Нет встроенного метода для получения размера/длины/подсчета словаря AS3. Существуют обходные пути: например, вы можете создать пользовательский класс словаря, который расширяет или обертывает класс flash.utils.Dictionary, добавляя функцию счетчика. Вы можете управлять счетчиком, когда записи добавляются/удаляются или рассчитываются по требованию с помощью простой итерации цикла:

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

Ответ 2

В идеале просто реализовать оболочку вокруг Словаря, которая расширяет класс Proxy. Это позволяет вам переопределять и перехватывать добавление и удаление свойств из Словаря, позволяя использовать новый класс Dictionary точно так же, как оригинал, с тем же синтаксисом и способностями, с добавлением функции длины, которая возвращает число ключи.

Эта реализация работает следующим образом. Когда свойство задано или удалено, оно проверяет, существует ли уже существующее свойство (строго оно равно undefined) и соответственно увеличивает или уменьшает внутренний счетчик длины. Эта реализация также автоматически удаляет запись, когда ее значение установлено на undefined для согласованности.

Я написал эту оболочку словаря только для этого вопроса; он занял около 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;
        }
    }
}

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: реализация выше, хотя наиболее перспективный подход, который мог бы работать теоретически, в конечном итоге является тупиком, поскольку словарь по своей сути несовместим с методами интерфейса прокси.

Во-первых, методы setProperty, getProperty и deleteProperty, как представляется, получают нетипизированные параметры name, но они на самом деле сильно типизировали объекты QName, которые существенно ограничивают ваши ключи именами типов String, так же, как Object и ассоциировать массивы. Dictionary не связано этим ограничением и позволяет использовать экземпляры объектов как уникальные ключи, поэтому он по своей сути несовместим с методами класса Proxy. Документация класса "Словарь" также имеет одну ноту и явно указывает, что объекты 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;
    }

Ответ 3

Вы можете использовать DictionaryUtil:

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