var d:Dictionary = new Dictionary(); d["a"] = "b"; d["b"] = "z";
Как получить длину/размер словаря (который равен 2)?
var d:Dictionary = new Dictionary(); d["a"] = "b"; d["b"] = "z";
Как получить длину/размер словаря (который равен 2)?
Нет встроенного метода для получения размера/длины/подсчета словаря 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;
}
В идеале просто реализовать оболочку вокруг Словаря, которая расширяет класс 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;
}
Вы можете использовать DictionaryUtil:
var dictionaryLength : int = DictionaryUtil.getKeys(d).length;