2010-03-05 7 views

Antwort

32

Es gibt keine integrierte Methode, um die Größe/Länge/Anzahl eines AS3-Wörterbuchs zu erhalten. Es gibt Problemumgehungen: Sie können z. B. eine benutzerdefinierte Wörterbuchklasse erstellen, die die Klasse flash.utils.Dictionary erweitert oder umschließt und die Zählerfunktionalität hinzufügt. Sie können die Zählung verwalten wie Einträge hinzugefügt/entfernt oder zählen On-Demand-For-Schleife mit einem einfachen Iteration:

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

Schade, einen Wrapper zu bauen hatte. –

+47

Wohin gehe ich, um Adobe dafür zu belasten? –

+1

Es war notwendig, Fehler in For-Schleifen zu vermeiden, d. H. Was passiert, wenn ein Array mit for..in durchlaufen wird. – Brilliand

0

Man würde im Idealfall implementieren nur einen Wrapper um Dictionary, das die Proxy-Klasse erweitert. Dadurch können Sie das Hinzufügen und Entfernen von Eigenschaften aus dem Dictionary überschreiben und abfangen, so dass die neue Dictionary-Klasse genau wie das Original verwendet werden kann, mit genau der gleichen Syntax und den gleichen Fähigkeiten, wobei eine Längenfunktion hinzugefügt wird, die die Zahl zurückgibt Schlüssel.

Diese Implementierung funktioniert wie folgt. Wenn eine Eigenschaft gesetzt oder gelöscht wird, prüft sie, ob die Eigenschaft bereits existiert (ob sie genau undefiniert ist), und inkrementiert oder dekrementiert den internen Längenzähler entsprechend. Diese Implementierung löscht auch automatisch einen Eintrag, wenn sein Wert aus Gründen der Konsistenz auf "nicht definiert" gesetzt ist.

Ich schrieb dieses Wörterbuch Wrapper nur für diese Frage; Es dauerte ungefähr 5 Minuten und es bietet eine Längenfunktion, die die Länge zurückgibt. Ich habe mich dafür entschieden, es zu einer Funktion und nicht zu einer Eigenschaft zu machen, so dass es die Eigenschaftsnamen oder die Aufzählung der Dictionary-Eigenschaften nicht beeinträchtigt.

BENUTZEN SIE DIESE UMSETZUNG NICHT; VERWENDEN SIE DAS, DAS IHNEN ANFOLGT. Ich erkläre warum unten.

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

HAFTUNGSAUSSCHLUSS: Die Implementierung oben, obwohl der vielversprechendste Ansatz, der in der Theorie gearbeitet haben könnte, ist letztlich eine Sackgasse, da Wörterbuch von Natur aus nicht mit den Methoden-Proxy-Schnittstelle ist.

Erstens, die setProperty, getProperty und deleteProperty Methoden erscheinen nicht typisierten name Parameter zu erhalten, aber sie sind typisiert tatsächlich stark QName Objekte, die im Wesentlichen Ihre Schlüssel zu String Typnamen beschränken, wie Object und Associate Arrays. Dictionary ist nicht an diese Einschränkung gebunden und ermöglicht die Verwendung von Objektinstanzen als eindeutige Schlüssel. Daher ist sie inhärent inkompatibel mit den Methoden der Proxy-Klasse. Die Dokumentation der Dictionary-Klasse enthält auch eine einzelne Notiz und es besagt explizit, dass QName-Objekte nicht als Schlüssel verwendet werden können.

Ebenso die nextName Methode der Proxy verhindert, dass Sie Aufzählen über alle Dictionary Schlüssel aus dem gleichen Grunde, weil es einen stark Typen Rückgabewert von String hat. Selbst wenn setProperty, getProperty tatsächlich nicht typisierte Schlüssel für die Namen akzeptiert, können Sie sie dennoch nicht über die Enumeration abrufen, da die Methode nextName nur den Typ string zurückgibt. Dictionary ist einfach eine Klasse für sich.

Das beste, was Sie tun können, ist die Implementierung eines Wrappers wie dem obigen, der das zugrundeliegende Wörterbuch für die Aufzählung verfügbar macht. Andere erfordern jedoch explizite addKey/removeKey-Methoden mit nicht typisierten Namen und Werten anstelle des Proxy-Verhaltens.

alle der oben genannten, eine bessere Umsetzung wäre wie folgt, in dem Sie das Wörterbuch manipulieren durch Verfahren wie getValue/setValue/removeValue Aufruf und haben Zugang zu einem Schlüssel-Enumeration sowie eine Länge Eigenschaft:

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

Sie können DictionaryUtil verwenden:

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