"banana" 但是,这不适用于动态哈希: "%{a}" % Hash.new -6ren">
gpt4 book ai didi

ruby - 使用带有字符串和 % 的动态查找散列

转载 作者:数据小太阳 更新时间:2023-10-29 08:11:46 24 4
gpt4 key购买 nike

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#fetchHash#has_key?,或其他任何东西;同样,您甚至不能将 Hash 子类化并覆盖任何方法来绕过 String#% 的脑损伤。

我认为你丑陋的解决方案没有其他方案那么丑陋(重新实现 String#%,破解一堆正则表达式,...)。

YMMV 当然还有其他 Ruby 实现。

关于ruby - 使用带有字符串和 % 的动态查找散列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31910205/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com