var d:Dictionary = new Dictionary(); d["a"] = "b"; d["b"] = "z";
Jak uzyskać długość/rozmiar słownika (co oznacza 2)?Pobierz rozmiar skryptu ActionScript 3
var d:Dictionary = new Dictionary(); d["a"] = "b"; d["b"] = "z";
Jak uzyskać długość/rozmiar słownika (co oznacza 2)?Pobierz rozmiar skryptu ActionScript 3
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;
}
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;
}
można użyć DictionaryUtil:
var dictionaryLength : int = DictionaryUtil.getKeys(d).length;
Szkoda, musiał zbudować otoki. –
Dokąd mam pójść, aby zrobić to za pomocą Adobe? –
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