如何在AS3中清除字典

3
这能在字典中工作,以清除所有键引用吗?
public static function cleanDic(_dic:Dictionary):void
{
    for (var eachKey:String in _dic)
    {
        delete _dic[eachKey];
    }
}

我担心在for循环中删除某些关键字会导致未清除所有元素。

这种情况是否会发生?

谢谢

3个回答

10

首先,我不喜欢这里给出的任何答案。现在解释一下:

  1. 你的代码将无法删除字典中的所有键,因为字典键可以是任何对象,而不一定是字符串。所以,你需要遍历:

    for (key:Object in dictionary) delete dictionary[key];

  2. 有很多合理的情况,当你不想创建一个新的字典时——创建一个新的字典有时是一个非常差的替代品。例如,在代码中的两个地方共享值(等等,你为什么要创建一个字典?)。一旦你创建了一个新的字典,代码中的这些位置就应该被通知并重新获取对新对象的引用。因此,有时删除字典中的所有键,虽然不像创建一个新的字典那样计算有效,但比起创建一个新的字典,它会使事情更简单。

  3. 字典有一个有趣的方面。它实际上是由两个哈希表实现的,一个包含字符串键,另一个包含指针键(对象键)。不幸的是,这更多是由于糟糕/没有思考的设计,而不是故意的。它继承了来自Object的字符串哈希表和自己的指针键哈希表。通常你想把字符串放进字典(或任何其他会隐式强制转换为字符串的东西,比如数字或逻辑值),所以当你发现自己在使用字典时使用字符串键,请再考虑一下,你可能应该使用Object

  4. 在循环字典期间会发生什么:在幕后创建一个键集合,实际上你是在遍历该集合。然而,由于字典的双重性质,两个键可能被视为相同的键(例如,如果你添加了一个字符串"1"和一个整数1键-你将得到其中的一个)。在删除这些键时,在不同版本的播放器中有不同的结果。在一些旧版本中存在一个 bug,即在删除这些键之后序列化字典之后,其中仍然存在一个这些键。但是,你应该避免使用字符串或数字作为键。


嗨,感谢您的建议。在我的情况下,我使用字典来存储一些需要快速更改的元素。例如,在第一个时刻,我会将一些元素设置为(A,B,C),而在第二个时刻,我需要首先清除字典,然后将其他元素推入(E,F,G)。这种情况可能每个时刻都会发生,那么在这种情况下,哪种方法最好?是每个时刻都创建一个新的字典还是清空它?对于在对象内部使用字典,我认为在字典中查询速度更快(这样正确吗?)再次感谢您的建议。 - Tunied
只是为了让这一点非常清楚,当你在第三点中说“不想将字符串放入字典”时,你是指将字符串作为值存储呢还是将它们用作键?如果是后者,你能再详细解释一下吗?因为这是我一直在做的事情,到目前为止还没有遇到任何问题。所以我真的很想知道可能有什么问题。 - AlBirdie
我认为这也值得一提 - 当您在迭代时删除字典中的键值对时...它可能会产生不可预测的结果(例如留下一些未被删除的项)。如果您像向前迭代(i++)一样从数组/向量中删除元素,您会将它们全部删除吗?可能不会。因此,我建议首先收集您的键(使用类似for(var k:* in yourDictionary) keys[keys.length] = k;的东西),然后迭代keys数组调用delete yourDictionary[keys[i]];来删除字典元素。 - chamberlainpi
1
它处理字符串和数字键的方式实际上相当奇怪。例如,dic[Number(1)] = "string 1"; 的结果是一个 'int' 类型的键(通过 getQualifiedClassName(key) 获得)。另一方面,dic[Number(-1)] = "string 1"; 的结果是一个 'String' 类型的键。同时,dic["1"] 的结果是一个 'int' 类型的键,但 dic["1."] 的结果是一个 String 键。这意味着 1 和 "1" 将不会产生不同的键(它们都将是值为 1 的 'int'),-1 和 "-1" 也是如此(它们都将是值为 "-1" 的 'String')。 - Triynko
总的来说,它将正整数(甚至是字符串类型)视为 int 类型键,其他数字(负数、小数等)和字符串视为字符串,所有其他对象都视为对象。它似乎尝试先将数字和字符串键转换为 int,如果失败了,就将其存储为字符串,对于所有其他类型,它使用自己的对象哈希。因此,它必须有三个内部哈希,一个用于 int 键,一个用于字符串键,另一个用于对象键。可能针对这三种类型的键进行了某种优化,并且实际上是有道理的,但强制将字符串键 "1" 转换为 1 是不合理的。 - Triynko
概述2:任何看起来像普通数字值的键,无论是字符串还是整数,正数或负数或分数,都将解析为相同的键。唯一的例外是类似于“-1.”和-1这样的情况,它们不会解析为相同的键,因为“-1.”将保持为字符串,而-1将成为字符串“-1”,其不等于“-1.”。当我说常规数字时,我的意思是数字转换为字符串后的样子,因此“-1”是常规数字,但“-1.”不是,因为没有数字会被格式化为这样的字符串。但“-1.5”将等同于1.5。 - Triynko

2

不需要编写清理 Dictionary 的方法。只需使用以下代码:

yourdictionary = new Dictionary();

并且GarbageCollector会解决这个问题。

你怎么看待 yourdictionary = null?如果你想销毁Dictionary对象,这种方式似乎更加直接。 - Tom Auger
Tom Auger分配一个引用(无论是null还是其他)与对Dictionary对象进行操作(例如清除其中的所有项)完全无关。 - undefined

2

我不太确定你的意思是什么

我担心在for循环期间删除某些键会导致未清理所有元素。

但是你的代码示例是正确的,这就是如何清除Dictionary。 (假设您只使用具有string键的Dictionary对象,因为您的for循环使用string。请参见下面工程师的评论。)

或者,您可以将字典设置为新实例-这样可以稍微更快地实现相同的效果:

var dict:Dictionary = new Dictionary ();

... // use dict here      

dict = new Dictionary (); // effectively cleans the dictionary

Flash垃圾回收器应该释放被丢弃的字典中的所有元素。__

+1,但是“但是您的代码示例是正确的,这就是Dictionary可以被清除的方法”完全不正确。Dictionary的键不只是String,还可以是其他对象。因此,代码中的var eachKey:String是不正确的。 - Engineer
@工程师 哎呀,对不起,你说得对。我会在答案中修复它。 - xxbbcc
谢谢,我的意思是有点担心,如果我们使用for(var i:int=0;i<array.length;i++){array.splice(i,1)}循环删除数组或向量中的多个对象,可能不会完全删除。我担心的是,如果在字典中删除一个元素也会导致“字典长度改变”。无论如何,感谢大家的帮助 :) - Tunied
@Tunied 这不应该是个问题 - 你可以在循环中删除任意数量的项目。但是,如果你使用循环计数器(i),你必须从vector的末尾开始删除(使用i--)。如果你向前删除(也就是说,你使用i++),你的循环计数器将增加,但你的元素计数将减少,当你尝试索引一个现在不存在的元素时,你会遇到错误。 - xxbbcc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接