如何递归地用“”替换红宝石哈希中的所有零值?
Posted
技术标签:
【中文标题】如何递归地用“”替换红宝石哈希中的所有零值?【英文标题】:How to replace all nil value with "" in a ruby hash recursively? 【发布时间】:2014-07-17 04:06:28 【问题描述】:str = "<a><b><c></c></b></a>"
hash = Hash.from_xml(str)
# => "a"=>"b"=>"c"=>nil
如何将哈希中的所有nil
s 替换为""
,以便哈希变为:
"a"=>"b"=>"c"=>""
【问题讨论】:
键总是字符串吗?什么是可能的值? @sawa 键是合法的哈希键。仅应更改nil
值。
任何对象都是合法的哈希键。您已经在问题中写道,只有 nil 应该被更改。
我相信这个想法是键没有改变,等于nil
的值将被更改为等于一个空字符串。
【参考方案1】:
这是一个不改变原始哈希的递归方法。
代码
def denilize(h)
h.each_with_object() |(k,v),g|
g[k] = (Hash === v) ? denilize(v) : v.nil? ? '' : v
end
示例
h = "a"=> "b"=> "c"=>nil
denilize(h) #=> "a"=> "b"=> "c"=>""
h = "a"=> "b"=> "c"=>nil , "d"=>3, "e"=>nil, "f"=>nil
denilize(h) #=> "a"=> "b"=> "c"=>"" , "d"=>3, "e"=>"", "f"=>""
【讨论】:
【参考方案2】:这将破坏原始哈希,并且不适用于无限递归的哈希。
def nil2empty(hash)
hash.keys.each do |key|
if hash[key].kind_of? Hash
nil2empty(hash[key])
else
hash[key] = '' if hash[key].nil?
end
end
true # of course, what else? :P
end
使用示例:
hash
=> "a"=>"b"=>"c"=>nil
nil2empty(hash)
=> true
hash
=> "a"=>"b"=>"c"=>""
【讨论】:
由于您的方法破坏了原始哈希,因此根据 Ruby 约定,适当的方法名称将是nil2empty!
。更确切地说,如果我们要进一步遵守约定,方法名称将是 nil_to_empty!
,它会返回 nil
。
@David bang 方法约定会破坏调用者对象。 nil2empty 不是 Hash 模型上的一种方法,它不会改变被调用者(我什至不知道是谁),我认为这是最好的离开。此外,根据this style guide(我通常使用的那个),bangs 方法应该只存在于非 bang 方法中。
啊,是的,你是对的。可能适合将类似的东西修补到Hash
虽然......如果这样做的话,我的约定将适用:P。
为了避免破坏原始哈希,您当然可以先进行深层复制。一种方法是使用Marshal#dump 和Marshal#load:hash_copy = Marshal.load(Marshal.dump(hash))
。【参考方案3】:
我知道这不是您期望的答案,但是如果您可以处理一个值而不是 "" ,则此代码有效
eval("a"=>"b"=>"c"=>nil.to_s.gsub("nil", "1")) #=> returns a hash #"a"=>"b"=>"c"=>1
【讨论】:
以上是关于如何递归地用“”替换红宝石哈希中的所有零值?的主要内容,如果未能解决你的问题,请参考以下文章