web-dev-qa-db-ja.com

ActionScript3辞書のサイズを取得する

var d:Dictionary = new Dictionary(); 
 d ["a"] = "b"; 
 d ["b"] = "z";

辞書の長さ/サイズ(2)を取得するにはどうすればよいですか?

30

AS3ディクショナリのサイズ/長さ/カウントを取得するための組み込みメソッドはありません。回避策があります。たとえば、flash.utils.Dictionaryクラスを拡張またはラップして、カウンター機能を追加するカスタムディクショナリクラスを作成できます。エントリの追加/削除時にカウントを管理したり、単純なForループの反復を使用してオンデマンドでカウントしたりできます。

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

理想的には、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;
        }
    }
}

免責事項:上記の実装は、理論的には機能する可能性のある最も有望なアプローチですが、辞書は本質的にプロキシインターフェイスメソッドと互換性がないため、最終的には行き止まりになります。

まず、setPropertygetProperty、およびdeletePropertyメソッドは、型指定されていないnameパラメーターを受け取るように見えますが、実際には強く型付けされたQNameオブジェクトです。 、これは基本的に、キーをStringのように、Object型名に制限し、配列を関連付けます。 Dictionaryはこの制限に拘束されず、オブジェクトインスタンスを一意のキーとして使用できるため、本質的にProxyクラスのメソッドと互換性がありません。 Dictionaryクラスのドキュメントにも1つの注記があり、QNameオブジェクトをキーとして使用できないことが明示的に記載されています。

同様に、プロキシのnextNameメソッドは、厳密に型指定された戻り値Dictionaryを持っているため、同じ理由ですべてのStringキーを列挙することを防ぎます。したがって、setPropertygetPropertyが実際に名前の型指定されていないキーを受け入れたとしても、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
Triynko

DictionaryUtilを使用できます。

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