Ruby哈希的“关键”功能有多贵?

时间:2013-05-02 12:44:15

标签: ruby hash key reverse-lookup

我正在使用一些哈希,其中某些哈希的值是其他哈希的关键。

我需要多次使用key来获取值的键,以便我可以使用它来访问另一个哈希中的内容。

我想知道这可能带来什么样的性能影响。在我的情况下,这些哈希的数量很少,而且内容很小,但我想在理论上知道。

我应该避免使用太多吗?与获取密钥的值相比,它的表现如何?

2 个答案:

答案 0 :(得分:2)

以这种方式思考:你偶尔会做一个额外的步骤来获得价值。无论何时使用条件测试并在计算中添加几个步骤,都会发生这种情况。

显而易见,与此相关的开销很小,但此时担心的是过早优化。通过使用Benchmark类来测试获取散列键的替代方法与正常方式相比,您可以感受到差异。

我怀疑你必须做几百万个循环才能看到明显的差异。


以下是我如何创建@fontanus提到的反向映射:

hash = {a:1, b:2}
hash.merge!(Hash[hash.values.zip(hash.keys)])

结果是:

{
    :a => 1,
    :b => 2,
     1 => :a,
     2 => :b
}

也可以通过将哈希强制转换为数组,将其展平并将其反转然后将其转换为哈希值来完成,但我发现这不如上面那么直观。 YMMV。

hash.merge!(Hash[*hash.to_a.flatten.reverse])

@steenslag提醒我Hash.invert。我知道有些东西但不记得方法名称:

>> hash.merge!(hash.invert)
{
    :a => 1,
    :b => 2,
     1 => :a,
     2 => :b
}

给他一个赞成票!

答案 1 :(得分:1)

在ruby 1.9.3和2.0.0中搜索是O(n)操作。

static VALUE
rb_hash_key(VALUE hash, VALUE value)
{
    VALUE args[2];

    args[0] = value;
    args[1] = Qnil;

    rb_hash_foreach(hash, key_i, (VALUE)args);

    return args[1];
}

rb_hash_foreach的实施:

void
rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
{
    struct hash_foreach_arg arg; 

    if (!RHASH(hash)->ntbl)
        return;
    RHASH_ITER_LEV(hash)++;
    arg.hash = hash;
    arg.func = (rb_foreach_func *)func;
    arg.arg  = farg;
    rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
}

然而,你的哈希很小。 @theTinMan对于过早优化是正确的,你不应该担心它。