【发布时间】:2011-01-24 02:43:11
【问题描述】:
var d:Dictionary = new Dictionary(); d["a"] = "b"; d["b"] = "z";
如何获取字典的长度/大小(为2)?
【问题讨论】:
标签: flash actionscript-3 actionscript dictionary hashtable
var d:Dictionary = new Dictionary(); d["a"] = "b"; d["b"] = "z";
如何获取字典的长度/大小(为2)?
【问题讨论】:
标签: flash actionscript-3 actionscript dictionary hashtable
没有内置方法可以获取 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;
}
【讨论】:
理想情况下,只需在 Dictionary 周围实现一个包装器,该包装器扩展了 Proxy 类。这允许您覆盖和拦截 Dictionary 中属性的添加和删除,允许使用新的 Dictionary 类与原始类完全一样,具有完全相同的语法和能力,并添加一个返回数量的长度函数键。
此实现的工作原理如下。当设置或删除一个属性时,它会检查该属性是否已经存在(是否严格等于未定义)并相应地增加或减少内部长度计数器。当条目的值设置为 undefined 以保持一致性时,此实现还会自动删除条目。
我为这个问题编写了这个 Dictionary 包装器;大约花了 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;
}
}
}
免责声明:上面的实现虽然是理论上可行的最有希望的方法,但最终是死路一条,因为 Dictionary 本质上与 Proxy 接口方法不兼容。
首先,setProperty、getProperty 和 deleteProperty 方法似乎接收无类型的 name 参数,但它们实际上是强类型的 QName 对象,这实际上将您的键限制为 String 类型名称,就像Object 和关联数组一样。 Dictionary 不受此限制的约束,允许使用对象实例作为唯一键,因此它与 Proxy 类方法本质上是不兼容的。 Dictionary 类的文档也有一个注释,它明确指出 QName 对象不能用作键。
同样,Proxy 的nextName 方法会阻止您枚举所有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;
}
【讨论】:
您可以使用 DictionaryUtil:
var dictionaryLength : int = DictionaryUtil.getKeys(d).length;
【讨论】: