我需要过滤嵌套哈希以返回特定属性组合的项目。如果属性存在则返回该哈希,如果该属性不存在则返回默认值。如果该属性设置为“none”,则不返回任何内容。请考虑以下哈希:
{
"size"=>{
"default"=>{
"jeans"=>"boyfriend"
},
"blue"=>"none"
},
"style"=>{
"default"=>{
"shoes"=>"boots"
},
"blue"=>{
"jeans"=>"jeggings"
}
}
}
如果颜色为“黑色”,那么
{
"size"=>{
"jeans"=>"boyfriend"
},
"style"=>{
"shoes"=>"boots"
}
}
或者如果颜色是'蓝色',那么
{
"size"=>{
},
"style"=>{
"jeans"=>"jeggings"
}
}
最好的方法是什么?我已经尝试了select和delete的各种组合,但最终得到一个数组或包含颜色键的哈希。
答案 0 :(得分:0)
让h
成为问题中给出的哈希值,如果我对问题的理解是正确的,则以下方法将返回所需的哈希值。
def doit(h, color)
h.each_with_object({}) do |(k,f),g|
c,v = f.find { |kk,_| kk != "default" }
if c == color
g[k] = v.is_a?(Hash) ? v : {}
else
g[k] = f["default"]
end
end
end
doit(h, 'black')
#=> {"size"=>{"jeans"=>"boyfriend"}, "style"=>{"shoes"=>"boots"}}
doit(h, 'blue')
#=> {"size"=>{}, "style"=>{"jeans"=>"jeggings"}}
第二个例子的步骤如下。
color = 'blue'
enum = h.each_with_object({})
#=> #<Enumerator: {"size"=>{"default"=>{"jeans"=>"boyfriend"},
# "blue"=>"none"}, "style"=>{"default"=>{"shoes"=>"boots"},
# "blue"=>{"jeans"=>"jeggings"}}}:each_with_object({})>
生成此枚举器的第一个值:
x = enum.next
#=> [["size", {"default"=>{"jeans"=>"boyfriend"}, "blue"=>"none"}], {}]
并传递给该区块。块变量设置为x
,其值由&#34;消歧&#34;确定:
(k,f),g = x
k #=> "size"
f ##=> {"default"=>{"jeans"=>"boyfriend"}, "blue"=>"none"}
g #=> {}
现在执行块计算。
c,v = f.find { |kk,_| kk != "default" }
#=> ["blue", "none"]
c #=> "blue"
v #=> "none"
作为
c == color
#=> "blue" == "blue" => true
我们计算
v.is_a?(Hash)
#=> false
因此执行作业
g[k] = {}
#=> {}
所以现在
g #=> {"size"=>{}}
现在生成h
的第二个和最后一个元素并将其传递给块。
x = enum.next
#=> [["style", {"default"=>{"shoes"=>"boots"},
# "blue"=>{"jeans"=>"jeggings"}}], {"style"=>{"jeans"=>"jeggings"}}]
(k,f),g = x
k #=> "style"
f #=> {"default"=>{"shoes"=>"boots"}, "blue"=>{"jeans"=>"jeggings"}}
g #=> {"size"=>"none"}
c,v = f.find { |kk,_| kk != "default" }
#=> ["blue", {"jeans"=>"jeggings"}]
c #=> "blue"
v #=> {"jeans"=>"jeggings"}
c == color
# "blue" == "blue" => true
v.is_a?(Hash)
#=> true
g[k] = v
#=> {"jeans"=>"jeggings"}
g #=> {"size"=>"none", "style"=>{"jeans"=>"jeggings"}}
并返回g
。
答案 1 :(得分:0)
以下是我在重构之后得到的结果。它工作和测试所有通过。可以做更多的重构。
class Filterer
def self.filter(facets, color)
acc = {}
facets.each do |k, facets|
facets.each do |_, facet|
acc[k] = color_facets(color, facets)
end
end
acc
end
def self.color_facets(color, facets)
return {} if no_facets?(color, facets)
facets[color] ? facets[color] : facets['default']
end
def self.no_facets?(color, facets)
facets[color] && facets[color] == 'no facet'
end
end