在方法的开头,我想检查之前是否使用这些确切的参数调用了该方法,如果是,则返回当时返回的结果。
起初,使用一个参数,我使用了一个字典,但现在我需要检查 3 个参数(一个字符串、一个对象和一个 bool 值)。
我尝试制作一个自定义对象,如下所示:
var cacheKey:Object = { identifier:identifier, type:type, someBoolean:someBoolean };
//if key already exists, return it (not working)
if (resultCache[cacheKey]) return resultCache[cacheKey];
//else: create result ...
//and save it in the cache
resultCache[cacheKey] = result;
但这不起作用,因为第二次调用该函数时,新的 cacheKey 是 不一样 对象作为第一个,即使它的属性是相同的。
所以我的问题是:是否有一种数据类型可以检查用作匹配键的键的对象的属性?
还有什么是我最好的选择?也为 key 创建缓存? :/
最佳答案
注意技术方案有两个方面:相等比较和 索引 .
悬崖笔记版本:
Object
跟踪它们(不是 Dictionary
)。 Object
参数,只需使用一个数组和 some
方法对所有缓存的键进行简单的比较。只有您知道实际方法的成本有多高,因此由您决定可接受的查找成本(取决于提供给函数的唯一参数的数量)。 平等比较
地址 相等比较编写一些代码来比较对象的属性值是很容易的,而不是为了引用相等性。以下函数强制执行严格的集合比较,因此两个对象必须包含具有相同值的完全相同的属性(不允许任何一个对象上的附加属性):
public static propsEqual(obj1:Object, obj2:Object):Boolean {
for(key1:* in obj1) {
if(obj2[key1] === undefined)
return false;
if(obj2[key1] != obj2[key1])
return false;
}
for(key2:* in obj2)
if(obj1[key2] === undefined)
return false;
return true;
}
您可以通过消除第二个 for 循环来加快速度,但要权衡
{A:1, B:2}
将被视为等于 {A:1, B:2, C:'An extra property'}
.索引
在您的情况下,问题在于您丢失了 索引那一个
Dictionary
提供引用相等或 Object
提供字符串键。您必须将每组新的函数参数与之前看到的参数的整个列表进行比较,例如使用 Array.some
.我用的领域currentArgs
以及避免每次生成新闭包的方法。private var cachedArgs:Array = [];
private var currentArgs:Object;
function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
currentArgs = { stringArg:stringArg, objArg:objArg, boolArg:boolArg };
var iveSeenThisBefore:Boolean = cachedArgs.some(compareToCurrent);
if(!iveSeenThisBefore)
cachedArgs.push(currentArgs);
}
function compareToCurrent(obj:Object):Boolean {
return someUtil.propsEqual(obj, currentArgs);
}
这意味着比较将是 O(n) 时间,其中 n 是不断增加的唯一函数参数集的数量。
如果您的函数的所有参数都是原始参数,请参阅非常相似的问题 In AS3, where do you draw the line between Dictionary and ArrayCollection? .标题听起来不太相似,但已接受的答案中的解决方案(是的,我写的)解决了完全相同的技术问题——使用多个原始值作为单个复合键。您的情况的基本要点是:
private var cachedArgs:Object = {};
function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
var argKey:String = stringArg + objArg.toString() + (boolArg ? 'T' : 'F');
if(cachedArgs[argKey] === undefined)
cachedArgs[argKey] = _yourMethod(stringArg, objArg, boolArg);
return cachedArgs[argKey];
}
private function _yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
// Do stuff
return something;
}
如果您真的需要确定哪个引用比另一个“大”(如
Dictionary
在内部所做的那样),您将不得不涉足一些丑陋的东西,因为 Adobe 尚未提供任何 API 来检索“值”/引用的“地址”。到目前为止我发现的最好的事情是这个有趣的黑客:How can I get an instance's "memory location" in ActionScript? .不做一堆性能测试,我不知道使用这个 hack 来比较引用是否会扼杀二叉搜索树 indexnig 获得的优势。当然,这将取决于 key 的数量。
关于actionscript-3 - 缓存具有多个参数的方法结果的最佳方法 - 对象作为字典中的键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14156102/