如何递归地用“”替换红宝石哈希中的所有零值?

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

如何将哈希中的所有nils 替换为"",以便哈希变为:

"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

【讨论】:

以上是关于如何递归地用“”替换红宝石哈希中的所有零值?的主要内容,如果未能解决你的问题,请参考以下文章

如何从红宝石中的哈希中收集许多属性

如何从红宝石中的哈希值乘以?

用先前的非零值替换向量中的所有零

用Python在给定目录及其子目录中递归替换文件中的字符串?

TSQL - 列中所有非零值的平均值

如何优雅地重命名 Ruby 中哈希中的所有键? [复制]