- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
"banana" 但是,这不适用于动态哈希: "%{a}" % Hash.new -6ren">
Ruby 的 %
格式化运算符允许使用散列来替换模板值:
"%{a}" % { a: "banana" } # => "banana"
但是,这不适用于动态哈希:
"%{a}" % Hash.new { |hash, key| hash[key] = "banana" } # => KeyError
有解决办法吗?
编辑:这个 Y 的 X 是从每个键的可能值数组创建格式散列。我目前的解决方案是这样的:
content = Hash[CONTENT.map { |k, v| [k, v.sample] }]
但是,我认为这非常丑陋,作为动态解决方案会更好。
最佳答案
我不认为你可以做你想做的事,至少不能用 MRI。
如果您跟踪代码,您会发现 String#%
最终在 sprintf.c
中用 C 语言实现。 %{x}
处理 C 实现的部分 does this :
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
键的值,然后是 KeyError
如果 rb_hash_lookup2
没有找到任何东西(即 rb_hash_lookup2
返回 Qundef
)则被引发。现在,如果我们看一下 rb_hash_lookup2
,我们会看到它明确地不使用 Hash 的默认值:
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;
}
请注意,如果找不到 key ,它会使用 def
参数而不是 Hash 的默认参数:
return def; /* without Hash#default */
如果您查看 Hash#[]
implementation你会看到它和 rb_hash_lookup2
之间的唯一区别是 return def;
被替换为:
return hash_default_value(hash, key);
这是你的问题:String#%
明确绕过了你的 Hash 的默认值逻辑。由于所有这些都是通过直接 C 调用发生的,因此您无法获取猴子补丁 Hash#[]
、Hash#fetch
、Hash#has_key?
,或其他任何东西;同样,您甚至不能将 Hash 子类化并覆盖任何方法来绕过 String#%
的脑损伤。
我认为你丑陋的解决方案没有其他方案那么丑陋(重新实现 String#%
,破解一堆正则表达式,...)。
YMMV 当然还有其他 Ruby 实现。
关于ruby - 使用带有字符串和 % 的动态查找散列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31910205/
我是一名优秀的程序员,十分优秀!