比较两个词典的最快方法是什么?

时间:2012-03-15 17:25:25

标签: actionscript-3 actionscript

我正在努力训练在Actionscript-3中匹配两个词典的最快方法。这就是我到目前为止所做的。

function compareDictionaries(p0:Dictionary, p1:Dictionary):Boolean 
{
    if(p0 == p1) {
        return true;
    } else {

        const matched:Dictionary = new Dictionary();
        for(var k0:Object in p0) {
            matched[k0] = k0;
            if(p0[k0] != p1[k0]) {
                return false;
            }
        }

        for(var k1:Object in p1) {
            if(matched[k1]) {
                continue;
            } else {
                if(p1[k1] != p0[k1]) {
                    return false;
                }
            }
        }

        return true;
    }
}

显然,使用项目的键创建一个新词典并不理想,但我真的不想重新测试匹配的项目(不知道这是否更慢或者没有!)。这当然可以通过在字典类上设置一个长度来避开,这将使第二个for循环冗余。

对此更好的想法?

修改

我创建了gist基准来显示成功匹配的结果(使用发布播放器)

(结果输出(ms)) 真正 43 真正 497 真正 22 真正 16

编辑2 我创造了另一个gist,显示了平等的错失。

(结果输出(ms)) 假 1 假 472 假 0 假 0

2 个答案:

答案 0 :(得分:1)

首先比较严格的平等。然后,测试两个词典中键的相等性:

  • 迭代属性并返回数组中的所有键
  • 测试相等的数组长度
  • 对数组进行排序
  • 再次迭代进行比较

只有通过所有这些测试,才能比较实际值:

public function areEqualDictionaries( dict1:Dictionary, dict2:Dictionary ):Boolean {
    if(dict1 === dict2) return true;

    var keys:Array = equalKeysArrayOrNull( dict1, dict2 ); 
    if(keys) 
        return haveEqualValues( keys, dict1, dict2 );
    else
        return false;
}

private function equalKeysArrayOrNull( dict1:Dictionary, dict2:Dictionary ):Array {
    var keys1:Array = enumerateKeys( dict1 ).sort();
    var keys2:Array = enumerateKeys( dict2 ).sort();
    if( keys1.length != keys2.length ) return null;

    var i:int = -1;
    while(++i < keys1.length) 
        if(keys1[i] !== keys2[i]) return null;

    return keys1;
}

private function haveEqualValues ( keys:Array, dict1 : Dictionary, dict2:Dictionary) :Boolean {
    for each (var key:* in keys) 
        if (dict1[key] != dict2[key]) return false;
    return true;
}

private function enumerateKeys( dict:Dictionary ):Array {
    var keys:Array = [];
    for(var key:* in dict) 
        keys.push( key );
    return keys;
}

请注意,字典使用identity(严格相等)来匹配键,这使得必须使用!==来比较它们。我想可以使用!=来比较这些值。

编辑:对比每个

的比较

这是我自己的基准forfor each

var dict : Dictionary = new Dictionary();
var keys : Array = [];
for (var i : int = 0; i < 1000000; i++) {
    var n : Object = { index:i };
    dict[n] = n;
    keys.push (n);
}

trace ("benchmark:");

trace ("----------");
var start : int = getTimer();

for each (var key:* in keys) {
    var m:* = dict[key];
}
var elapsed : int = getTimer() - start;
trace ("for each:" + elapsed);

trace ("----------");
start = getTimer();

for (var j:int = 0; j < keys.length; j++) {
    var o:* = dict[keys[j]];
}
elapsed = getTimer() - start;
trace ("for:" + elapsed);

在我的机器上返回:

for each:213
----------
for:274

答案 1 :(得分:1)

像这样简单的东西应该有用 - 没有新的数组/字典等:

public function compareDictionaries( d1:Dictionary, d2:Dictionary ):Boolean
{
    // quick check for the same object
    if( d1 == d2 )
        return true;

    // check for null
    if( d1 == null || d2 == null )
        return false;

    // go through the keys in d1 and check if they're in d2 - also keep a count
    var count:int = 0;
    for( var key:* in d1 )
    {
        // check if the key exists
        if( !( key in d2 ) )
            return false;

        // check that the values are the same
        if( d1[key] != d2[key] )
            return false;

        count++;
    }

    // now just make sure d2 has the same number of keys
    var count2:int = 0;
    for( key in d2 )
        count2++;

    // return if they're the same size
    return ( count == count2 );
}

从技术上讲,您可以直接与值进行比较(如不检查d2中是否存在密钥),就好像您搜索不存在的密钥一样,它应该解析为null (或undefined,我不是百分百肯定的),但如果d1中的值为空且d2 <中不存在,我将其留在那里/ p>