Ruby哈希数组过滤遇nil报错:如何处理properties为nil的元素?
问题描述
现有如下Ruby哈希数组:
question["options"] => [{"id"=>10217, "title"=>{"English"=>"Da A a E"}, "value"=>"Da A a E", "properties"=>{"disabled"=>false}}, {"id"=>10218, "title"=>{"English"=>"Profondo"}, "value"=>"Profondo", "properties"=>{"disabled"=>true, "piping_exclude"=>"false", "show_rules"=>nil, "show_rules_logic_map"=>nil}}, {"id"=>10219, "title"=>{"English"=>"La macchina da caffè a capsule"}, "value"=>"La macchina da caffè a capsule", "properties"=>{"disabled"=>true, "piping_exclude"=>"false", "show_rules"=>nil, "show_rules_logic_map"=>nil}}, {"id"=>10234, "title"=>{"English"=>"Extender Wifi"}, "value"=>"Extender Wifi", "properties"=>{"disabled"=>true, "piping_exclude"=>"false", "show_rules"=>nil, "show_rules_logic_map"=>nil}}, {"id"=>10246, "title"=>{"English"=>"Da A a F"}, "value"=>"Da A a F", "properties"=>{"disabled"=>false}}, {"id"=>10247, "title"=>{"English"=>"Sistematico"}, "value"=>"Sistematico", "properties"=>{"disabled"=>true, "piping_exclude"=>"false", "show_rules"=>nil, "show_rules_logic_map"=>nil}}, {"id"=>10250, "title"=>{"English"=>"4"}, "value"=>"4", "properties"=>{"disabled"=>true, "piping_exclude"=>"false", "show_rules"=>nil, "show_rules_logic_map"=>nil}}, {"id"=>10252, "title"=>{"English"=>"Ruote"}, "value"=>"Ruote", "properties"=>{"disabled"=>true, "piping_exclude"=>"false", "show_rules"=>nil, "show_rules_logic_map"=>nil}}, {"id"=>10268, "title"=>{"English"=>"Sub 8 GHz"}, "value"=>"Sub 8 GHz", "properties"=>{"disabled"=>true, "piping_exclude"=>"false", "show_rules"=>nil, "show_rules_logic_map"=>nil}}, {"id"=>10273, "title"=>{"English"=>"La copertura sul territorio"}, "value"=>"La copertura sul territorio", "properties"=>{"disabled"=>true, "piping_exclude"=>"false", "show_rules"=>nil, "show_rules_logic_map"=>nil}}, {"id"=>10280, "title"=>{"English"=>"Da A a G"}, "value"=>"Da A a G", "properties"=>nil}]
需要过滤数组,移除所有["properties"]["disabled"]为true的元素,同时将保留的元素转换为指定结构。原代码如下:
question["options"].filter{ |o| unless o["properties"].dig("disabled") { "value": o["value"], "id": o["id"], "text": { "it": o["title"]["English"] } } end }
但因最后一个元素的properties为nil,执行时抛出错误:
undefined method `dig' for nil:NilClass
解决办法
问题出在当properties为nil时,直接调用dig会触发NoMethodError。可以通过两种方式修复:
方法一:使用安全导航操作符&.
结合filter_map(同时完成过滤和映射,比filter更适合当前场景),代码如下:
question["options"].filter_map do |o| # 仅当disabled不为true时保留元素:properties为nil 或 disabled为false next unless o["properties"]&.dig("disabled") != true { "value": o["value"], "id": o["id"], "text": { "it": o["title"]["English"] } } end
&.是Ruby的安全导航操作符,当o["properties"]为nil时,o["properties"]&.dig("disabled")会返回nil,不会触发报错;filter_map会自动忽略next返回的nil,只收集我们构造的哈希对象。
方法二:用fetch给properties设置默认空哈希
如果偏好更明确的默认值处理,可使用fetch方法:
question["options"].filter_map do |o| # 当properties不存在时,返回空哈希,避免dig报错 disabled = o.fetch("properties", {}).dig("disabled") # 仅当disabled为true时跳过该元素 next if disabled == true { "value": o["value"], "id": o["id"], "text": { "it": o["title"]["English"] } } end
o.fetch("properties", {})确保即使properties为nil,也能拿到空哈希,调用dig不会报错;- 空哈希调用
dig("disabled")返回nil,不会触发next if disabled == true,因此properties为nil的元素会被保留。
内容的提问来源于stack exchange,提问作者Roberto Pezzali
相关产品推荐
相关产品推荐

