2010-03-05 17 views

Odpowiedz

32

Nie ma wbudowanej metody uzyskania rozmiaru/długości/liczby słowników AS3. Istnieją obejścia: na przykład można utworzyć niestandardową klasę słownika, która rozszerza lub opakowuje klasę flash.utils.Dictionary, dodając funkcję licznika. Można zarządzać rachubę jako wpisy są dodawane/usuwane, lub liczyć na żądanie za pomocą prostego Dla iteracji pętli:

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

Szkoda, musiał zbudować otoki. –

+47

Dokąd mam pójść, aby zrobić to za pomocą Adobe? –

+1

Konieczne było uniknięcie pułapek w pętlach For, tzn. Co się dzieje, gdy pętla nad tablicą zawiera wartość for..in. – Brilliand

0

Można by idealnie tylko wdrożyć otoki wokół Dictionary, który rozszerza klasę Proxy. Pozwala to na przesłonięcie i przechwycenie dodawania i usuwania właściwości ze słownika, dzięki czemu nowa klasa Dictionary będzie używana dokładnie tak samo jak oryginał, z tą samą składnią i zdolnościami, z dodatkiem funkcji długości, która zwraca liczbę klawiatura.

Ta implementacja działa w następujący sposób. Kiedy właściwość jest ustawiona lub usunięta, sprawdza, czy właściwość już istnieje (czy jest ściśle równa się niezdefiniowanemu) i odpowiednio zwiększa lub zmniejsza wewnętrzną licznik długości. Ta implementacja automatycznie usuwa wpis, gdy jego wartość jest ustawiona na undefined dla spójności.

Napisałem to opakowanie ze Słownikiem tylko dla tego pytania; zajęło to około 5 minut i zapewnia funkcję długości, która zwraca długość. Zdecydowałem się uczynić z niego funkcję, a nie własność, aby nie zakłócała ​​ona nazw właściwości ani wyliczania właściwości Słownika.

NIE UŻYWAĆ NINIEJSZEJ REALIZACJI; KORZYSTAJ Z JEDNEJ, KTÓREJ POSTANOWI GO. Wyjaśnię, dlaczego poniżej.

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; 
     } 
    } 
} 

ZASTRZEŻENIE: Realizacja powyżej, chociaż najbardziej obiecującym podejściem, które mogły pracował w teorii, jest ostatecznie ślepy zaułek, ponieważ słownik jest z natury niezgodne z metod interfejsu proxy.

pierwsze, setProperty, getProperty i deleteProperty metody wydają się otrzymać bez typu name parametry, ale w rzeczywistości są silnie wpisany QName obiektów, które zasadniczo ograniczają swoje klucze do String nazw typu, podobnie jak Object i tablice stowarzyszonych. Dictionary nie jest związany tym ograniczeniem i pozwala używać instancji obiektu jako kluczy unikalnych, dlatego jest z natury niezgodny z metodami klasy Proxy. Dokumentacja klasy Dictionary ma również jedną nutę i wyraźnie stwierdza, że ​​obiektów QName nie można używać jako kluczy.

Podobnie metoda Proxy nextName uniemożliwia wyliczanie nad wszystkimi Dictionary klucze z tego samego powodu, ponieważ ma silnie typu wartości zwracanej String. Więc nawet jeśli setProperty, getProperty rzeczywiście zaakceptował niepoprawne klucze dla nazw, nadal nie będzie można ich odzyskać poprzez wyliczenie, ponieważ metoda nextName zwraca tylko ciąg znaków typu. Dictionary jest po prostu klasą samą w sobie.

Najlepszą rzeczą, jaką można zrobić, to zaimplementować opakowanie podobne do powyższego, które eksponuje słownik bazowy do wyliczania, ale inne wymagają wywoływania jawnych metod addKey/removeKey z nie wpisanymi nazwami i wartościami zamiast używania zachowania Proxy.

Biorąc pod uwagę wszystkie powyższe, lepsza realizacja będzie w następujący sposób, gdzie można manipulować słownika poprzez wywołanie metody takie jak getValue/setValue/removeValue i mają dostęp do kluczy wyliczenie, jak również właściwości 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

można użyć DictionaryUtil:

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