2010-03-05 2 views

ответ

32

Нет встроенного метода для получения размера/длины словаря 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; 
} 
+1

Жаль, пришлось построить обертку. –

+47

Где я могу сделать Adobe Adobe для этого? –

+1

Нужно было избегать gotchas в циклах For, то есть что происходит при переходе по массиву с помощью in..in. – Brilliand

0

Казалось бы, в идеале просто реализовать обертку словаря, который расширяет класс 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; 
    } 
0

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

var dictionaryLength : int = DictionaryUtil.getKeys(d).length; 
Смежные вопросы