首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对字符串和%使用动态查找哈希

对字符串和%使用动态查找哈希
EN

Stack Overflow用户
提问于 2015-08-10 08:42:44
回答 2查看 270关注 0票数 4

Ruby的%格式化操作符允许使用散列来替换模板值:

代码语言:javascript
复制
"%{a}" % { a: "banana" } # => "banana"

然而,这不适用于动态哈希:

代码语言:javascript
复制
"%{a}" % Hash.new { |hash, key| hash[key] = "banana" } # => KeyError

有什么解决方法吗?

编辑:X到这个Y是从每个键的可能值的数组中创建一个格式散列。我目前的解决方案是这样的:

代码语言:javascript
复制
content = Hash[CONTENT.map { |k, v| [k, v.sample] }]

然而,我认为这相当丑陋,作为一个动态解决方案会更好。

EN

回答 2

Stack Overflow用户

发布于 2015-08-10 10:09:50

我认为你不能随心所欲,至少用核磁共振是不行的。

如果您仔细查看代码,就会发现sprintf.c中的String#%最终是用C实现的。C实现does this%{x}处理部分

代码语言:javascript
复制
if (sym != Qnil) nextvalue = rb_hash_lookup2(hash, sym, Qundef);
if (nextvalue == Qundef) {
    rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start);
}

rb_hash_lookup2调用用于从hash获取sym键的值,如果rb_hash_lookup2未找到任何内容(即rb_hash_lookup2返回Qundef),则会引发KeyError。现在,如果我们看一下rb_hash_lookup2,我们会发现它显式地没有使用哈希默认值:

代码语言:javascript
复制
VALUE
rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
{
    st_data_t val;

    if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
        return def; /* without Hash#default */
    }
    return (VALUE)val;
}

请注意,如果找不到键,它将使用def参数,而不是散列的默认值:

代码语言:javascript
复制
return def; /* without Hash#default */

如果您查看Hash#[] implementation,您会发现它与rb_hash_lookup2之间唯一的区别是return def;被替换为:

代码语言:javascript
复制
return hash_default_value(hash, key);

这就是你的问题:String#%显式地绕过了你的哈希默认值逻辑。由于所有这些都是通过直接C调用实现的,所以您无法获取猴子补丁Hash#[]Hash#fetchHash#has_key?或其他任何内容;类似地,您甚至不能子类Hash并覆盖任何方法来绕过String#%的脑损伤。

我认为你的丑陋的解决方案比其他的解决方案(重新实现String#%,修改一堆正则表达式,等等)要好一些。

YMMV,当然还有其他Ruby实现。

票数 0
EN

Stack Overflow用户

发布于 2015-08-10 10:16:32

您可以使用Hash#values_at显式初始化字符串的键,但这是一种技巧:

代码语言:javascript
复制
"%{a}, %{b}" % Hash.new {|h, k| h[k] = "banana" }.tap {|h| h.values_at(:a, :b) }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31910205

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档