var d:Dictionary = new Dictionary(); d["a"] = "b"; d["b"] = "z";
Как получить длину/размер словаря (что равно 2)?Получить размер словаря ActionScript 3
var d:Dictionary = new Dictionary(); d["a"] = "b"; d["b"] = "z";
Как получить длину/размер словаря (что равно 2)?Получить размер словаря ActionScript 3
Нет встроенного метода для получения размера/длины словаря 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 для обеспечения согласованности.
Я написал эту оболочку словаря только для этого вопроса; он занял около 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;
}
}
}
ОТКАЗ: Реализация выше, хотя наиболее перспективный подход, который мог бы работать в теории, в конечном счете тупик, так как словарь по своей сути несовместим с методами интерфейса Proxy.
Во-первых, setProperty
, getProperty
и deleteProperty
методы появляются получить нетипизированными name
параметры, но на самом деле они сильно типизированных QName
объекты, которые существенно ограничивают ключи к String
имен типов, так же, как Object
и ассоциированными массивам. Dictionary
не связан этим ограничением и позволяет использовать экземпляры объектов как уникальные ключи, поэтому он по своей сути несовместим с методами класса Proxy. Документация класса Dictionary также содержит одну ноту и явно указывает, что объекты QName нельзя использовать в качестве ключей.
Аналогично, nextName
метод Proxy предотвращает вас от перечисления по всем Dictionary
ключей по той же причине, потому что она имеет возвращаемое значение сильно типа в String
. Таким образом, даже если setProperty
, getProperty
фактически приняли нетипные ключи для имен, вы все равно не сможете получить их через перечисление, потому что метод nextName
возвращает только строку типа. Dictionary
просто в своем классе.
Лучшее, что вы могли бы сделать, это реализовать оболочку, подобную той, которая приведена выше, которая предоставляет базовый словарь для перечисления, но другим требуется вызывать явные методы addKey/removeKey с нетипизированными именами и значениями вместо использования поведения прокси.
Учитывая все вышесказанное, лучше реализация будет выглядеть следующим образом, где вы манипулируете словарь, вызывая такие методы, как GetValue/SetValue/removeValue, и иметь доступ к перечислению ключей, а также свойство длины:
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;
Жаль, пришлось построить обертку. –
Где я могу сделать Adobe Adobe для этого? –
Нужно было избегать gotchas в циклах For, то есть что происходит при переходе по массиву с помощью in..in. – Brilliand